Building a web app with Ruby on Rails

If you're having trouble deciding between Sinatra and Rails, Tim Millwood can help

In this tutorial I discussed Sinatra and walked through how to build an application to allow users to add and delete todo list items, as well as marking them as done. In this article we will work through building exactly the same application, but this time using Ruby on Rails. As both Sinatra and Ruby on Rails are based on the Ruby programming language and both use Rack as their foundation the article will also look at the differences and suggest why you may want to use one over the other.

For this application, we’ll be using the recently released Rails 4.0.0. This will work with Ruby 1.9.3 and Ruby 2.0.0. In this article, we’ll be working with Ruby 2.0.0. Once you have this installed along with RubyGems we can go ahead and install rails.

  1. gem install rails

The command above will download and install the latest version (4.0.0) of Rails for you. We can then start to make use of it by generating a new application and changing into the generated directory.

  1. rails new todo_lists
  2. cd todo_losts

The following will set up an skeleton application ready for us to use:

  1. rails generate scaffold item content:text done:boolean

The above command will generate some scaffolding and, although it won’t do everything we need, will get us most of the way. You’ll see after running the command that you have a controller called items_controller.rb in the app/controllers directory, a model called item.rb in the app/models directory and a bunch of views in the app/views/items directory.

In the db/migrate directory you’ll see that the scaffold command created a migration. Migrations are used to handle changes to the database schema. In this case we wanted to add an items table with two main columns: content (which we need to be a text type) and done (which we need to be a boolean type). By default, Rails will add an auto-incrementing id column, and also timestamps in the form of a created_at and updated_at column.

To run this migration and generate the database tables, we can use the following command.

  1. rake db:migrate RAILS_ENV=development

Even at this early stage we can run the command rails server to start the in-built rails server. This will allow you to access the application at, but returns the default Rails 'Welcome aboard' page.

To remove this, we need to edit the config/routes.rb file. In here, you will find the line resources :items, which was added by the scaffold command. This added all of the routes to create, read, update and delete the todo list items.

Above this, add root items#index, which add the root route pointing to the index action of the items controller. Now refreshing the page at will show the index page of all todo list items. This is the same action in the items controller that can be accessed via You can see there is a link to create a new item. Once created, these items can be viewed edited and deleted using the Show, Edit, Destroy links. Therefore, this gives us all the functionality needed. 

We'll use the new Bootstrap 3 via BootstrapCDN. To do this we need to replace a few lines in the app/views/layouts/application.html.erb. Replace:

  1. <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
  2. <%= javascript_include_tag "application", "data-turbolinks-track" => true %>

... with:

  1. <%= stylesheet_link_tag "//", "application", media: "all", "data-turbolinks-track" => true %>
  2. <%= javascript_include_tag "//", "application", "data-turbolinks-track" => true %>

This will now load in both the Bootstrap CSS and JavaScript. It won't affect any of the standard or custom CSS and JavaScript added to the Rails app due to the application reference still being within the tags.

Now that the Bootstrap CSS and JavaScript is being loaded, we need to replace the HTML in the views to follow the Bootstrap framework. This would end up being a lot of lengthy markup for this tutorial. Therefore, take a look in the /app/views/ on

The only missing item now is marking items as done (or not done) via Ajax. Rails has created a JavaScript file in /app/assets/javascripts/ called For this example, we’re not going to use CoffeeScript, we’ll just use standard JavaScript with jQuery. Therefore, rename with items.js:

  1. $(document).ready(function() {
  2.   $(".check").click(function(e) {
  3.     var item_id = $(this).parents('li').attr('id');
  4.     done = $(this).hasClass('done') ? 1 : 0
  5.     $.ajax({
  6.       type: "POST",
  7.       dataType: "json",
  8.       url: "/items/" + item_id,
  9.       data: { _method:'PUT', item: { done: done } },
  10.       }).done(function(data) {
  11.         if(done) {
  12.           $("#" + item_id + " a.done").text('Not done').removeClass('done').addClass('not_done');
  13.           $("#" + item_id + " .item").wrapInner("<del>");
  14.         }
  15.         else {
  16.           $("#" + item_id + " a.not_done").text('Done').removeClass('not_done').addClass('done');
  17.           $("#" + item_id + " .item").html(function(i, h) {
  18.             return h.replace("<del>", "");
  19.           });
  20.         }
  21.     });
  22.     e.preventDefault();
  23.   });
  24. });

The above code can then be added to items.js and will allow todo items to be marked as done via an Ajax call. The default code we generated via the scaffold command allows HTML and JSON formats so no changes are needed on the server side. The jQuery code works on a click event of the done (or not done) button. It then looks at if the button is to mark the item as done or not done based on the class, before making an Ajax call to the rails backend. With a successful update it then wraps or unwraps the item in a <del> tag and also updates the button.

So, that’s it. The app is complete. As you saw, most of the development was handled by the scaffold command. This is because the todo list app is a very simple Create, Read, Update, Delete (CRUD) type application. The only real custom development was to add in Bootstrap for the views and add in the jQuery for items to be marked as done via an Ajax call.

There are many situations where the scaffold command isn’t useful and it’s best to do things manually, so take time to look through the config/routes.rb and app/controllers/items_controller.rb files to see how things are constructed. Even in this example it’s added something that we don’t really need, such as the edit page, that after adding your first todo item you will find at http://localhost:3000/items/1/edit.

If you've read the version of this tutorial using the Sinatra framework, you’ll understand that the scaffolding has made the Rails version a lot simpler to build. However, at nearly three times the codebase size, the Rails version has got a lot of bloat which is not needed for smaller apps. You should also find the Sinatra version runs a little faster under load too.

Sinatra and Rails both have their place and the line between the two can often be fine. For example, with this todo list app, it’s small enough to say it might actually be better in Sinatra. But, if adding authentication, roles and more complexities, Rails would be the winner.

Therefore, starting with Rails makes sense if the intention is to grow it. Apps that will always be small, as well as those that are pretty custom such as APIs and those that don’t follow standard CRUD patterns, are best run on Sinatra.

See here for Millwood's tutorial of building an application to allow users to add and delete todo list items using the Sinatra framework.

Words: Tim Millwood

Tim is a client advisor at Acquia and freelance web developer, and an active member of the Drupal community.