Skip to main content

The Robot Factory – Part One

By Darren Jones



😳 Ever felt a little embarassed sharing your JavaScript? Let's fix it.


Adding and Deleting Resources in Sinatra

In this tutorial I’m going to go through how to use Sinatra to add and remove resources to and from a database.

To demonstrate this, I’m going to build a tiny web app called The Robot Factory that allows users to ‘build’ a production line of robots. Each robot will be saved to a database with randomly chosen head, body and legs and can also be deleted after it has been built. You can see the final version running here – You can also see all of the finished code here –

To follow this tutorial you will need to have the following gems installed:

$ gem install sinatra data_mapper sqlite3 dm-sqlite-adapter slim sass

Before I started, I used the brilliant Inkscape to draw a some cool looking robot parts and then saved them as top1.png, top2.png, middle1.png … etc. You can find all the files here, but feel free to create your own images using the same naming conventions.

Building the App

Everything in this app is going to be in the same file, so open up your favourite text editor and save the file as `main.rb`.  To start with, we need to require some gems and set up the database in DataMapper.

%w[sinatra dm-core dm-migrations slim sass].each{ |lib| require lib } 
DataMapper.setup(:default, ENV['DATABASE_URL'] || File.join("sqlite3://",settings.root, "development.db"))

Next is the Robot Class. As you can see, the robot class has 4 properties: an auto-incrementing id and 3 integers that correspond to the top, middle and bottom images. These integers are generated by using a Proc to set the default value as a random number that corresponds to how many top,middle and bottom images there are:

class Robot 
  include DataMapper::Resource 
  property :id, Serial 
  property :top, Integer, :default => proc { |m,p| 1+rand(6) } 
  property :middle, Integer, :default => proc { |m,p| 1+rand(4) } 
  property :bottom, Integer, :default => proc { |m,p| 1+rand(5) } 


Now that the Robot model is set up, it needs migrating to the database. Open up a terminal and navigate to the folder where you have saved the main.rb file, then type the following:

$> irb
ruby-1.9.2-p180 :002 > require './main'
=> true
ruby-1.9.2-p180 :003 > Robot.auto_migrate!
=> true

Route Handlers

The next job is to create the route handlers. The first allows the CSS to be written as inline-views  in the same document.

get('/styles.css'){ scss :styles }

Next, we will create the three main handlers. The first is the index page, which is actually the only page in the Robot Factory. It gets all the robot objects in the database and stores them as an array in the instance variable @robots that can be accessed in the views. The second deals with the post request that is actioned when the ‘BUILD A ROBOT’ button is pressed. This creates a new robot then redirects back to the index page, where the new robot will become part of the @robots array. The last handler deals with deleting the robots. It finds the robot that was deleted using the :id part of the url and then removes it from the database using DataMapper’s destroy method. It then redirects back to the index page where that robot will no longer be part of the @robots array.

get '/' do 
  @robots = Robot.all 
  slim :index 

post '/build/robot' do 
  redirect to('/')

delete '/delete/robot/:id' do 
  redirect to('/')



Now, it’s time for some views. In this example, I’ve chosen to use inline views so that they can be included in the same file. I’m also using the awesome Slim templating language to write them in.

The first is a fairly standard HTML 5 layout. I’ve also included a link to some fonts from the Google Web Font Directory that I will be using in the CSS later.

doctype html 
    meta charset="utf-8" 
    title Robot Factory 
    link rel="shortcut icon" href="/fav.ico" 
    link href="|Ubuntu&v2" rel='stylesheet' 
    link rel="stylesheet" media="screen, projection" href="/styles.css" 
    /[if lt IE 9] 
      script src="" 
  body == yield 
    footer role="contentinfo" 
      p Building Quality Robots since 2011

The next view is the index page which is the only page in the app. It basically includes a button inside a form that is pressed to build a robot, as well as a list of robots if any exist. If no robots exists yet, a message will appear telling you to get on and build some. I’ve separated the code for the robot into a separate view and included it as a partial (==slim :robot, :locals => { :robot => robot }, this is usually a good idea anyway, but has extra benefits when dealing with Ajax as we shall see later.

h1 Robot Factory action="/build/robot" method="POST" 
  input.button type="submit" value="Build A Robot!" 
-if @robots.any? 
  ul#robots - @robots.each do |robot| 
    ==slim :robot, :locals =>; { :robot =>; robot } 
- else 
  h2 You Need To Build Some Robots!

The code for the robot places the three images that form its body inside a list item. There is also a form at the end that is used for the delete button. This has to be part of a form so that the correct HTTP verb DELETE can be used (notice the hidden form field that is used to tell Sinatra that this is actually a DELETE request).

  img src="{}.png"
  img src="{robot.middle}.png" 
  img src="{robot.bottom}.png" 
  form.destroy action="/delete/robot/#{}" method="POST"   
    input type="hidden" name="_method" value="DELETE" 
    input type="submit" value="×"

The app is now fully complete and will run perfectly well as it is, although it won’t look very good. The main problem is that the images that make up the robots are displayed side by side, rather than vertically on top of each other as intended.

Adding Some Style

This is all sorted out by applying some styles. Earlier on, we added a handler that allowed us to place our CSS into the views, since we’re using inline views, it just goes underneath the other views in the same file:

html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote, pre,abbr,address,cite,code,del,dfn,em,img,ins,kbd,q,samp,small,strong,sub,sup,var,b,i,dl,dt, dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article, aside, canvas, details,figcaption,figure,footer,header,hgroup,menu,nav,section, summary,time,mark,audio,video {


footer {
  border-top:3px solid #4b947d;

h1 {
  margin:5px 40px;

.button { 
  padding: 6px 12px;

#robots {
.robot { 
  padding:10px 0; 
  form {
  &:hover form {
  form input {
    padding:0 4px; 
  img {
    padding:0 10px;

This is all very standard stuff. It starts off with a basic reset, then sets all the fonts and colors for the body, footer, and headings. The ‘Build A Robot’ button is styled so that it is nice, bright and rounded (like all good web 2.0 buttons should be). The robots are floated left, so they will appear side by side and the images set to display:block which forces them to sit on top of each other. The form that contains the delete button is set to be hidden, unless the robot is hovered on. It has also been styled to look like a standard ‘delete’ button.

The app now works, and looks as it should, but there are some page reloads every time you try to build or destroy a robot that slow the whole process down. This sounds like a job for the XMLHttpRequest … but that will have to wait until part 2 of this tutorial!

In the meantime, crank out some robots to keep you company…

Daz has been programming and building websites since the start of the millennium. He enjoys using Ruby and JavaScript and loves them both in their own special ways. He is the author of JavaScript: Novice to Ninja and Jump Start Sinatra. He also produced the 'Getting Started With Ruby' video tutorials for SitePoint and has written a number articles for SitePoint’s website. He was born in the city of Manchester and still lives there, where he teaches mathematics and enjoys playing water polo.

New books out now!

💁‍♀️ Fun Fact: Python was ranked #2 on a recent highest paid coders list. *

🤓 Ok. When did a code editor from Microsoft become kinda cool!?