Building a CRUD application with Sinatra

By Nick Rodriguez

While Rails dominates the Ruby-web space with it's patented 'Rails Magic' being seen everywhere from Github to Groupon, Sinatra still plays a vital role for many smaller applications that don't quite need the overhead of a larger, more powerful framework. Since Sinatra is specifically designed to be lightweight and flexible, it's a great framework to use to test out different bits of other frameworks like ActiveRecord or MVC patterns, as it forces you to become intimately familiar with them, by forgoing the hidden magic present in other frameworks.

To get started building our small app, we'll use the Sinatra app generator Corneal

Install Corneal and Generate a New App

$ gem install corneal

$ corneal new crud-app

$ cd crud-app

$ bundle install

Design Domain Model

This may be the most important step in building your app. You need to be sure of all the relations between your models before you begin building them, otherwise, you'll end up spending hours trying to figure out why, for example, a review owns a user instead of the other way around. Additionally, the next two steps are much faster if you've got a complete domain model specced out ahead of time. Here's the model we'll use for this app:

sinatra_crud_db_model.png
Movie review domain model

Generate Models/Views/Controllers/Migrations 

Corneal's scaffold command generates a complete MVC architecture for the model name you pass to it. So if we ran $ corneal scaffold new_model, we'd get the following new files.

sinatra_crud_mvc_scaffold.png
mmm...Freshly baked files

You can also pass additional arguments of the form attribute:data_type to have it also generate a database migration for you. So for our domain, we'll run the following commands.

$ corneal scaffold movie name:string

$ corneal scaffold user username:string email:string password_digest:string

$ corneal scaffold review content:string rating:integer

This will likely generate more views than we need, (we probably won't want a Users index, for example) but we can clean up these extra files later.

Build Models

Now that we've got all the files we should need, we can build the models.

sinatra_crud_models.PNG
Reviews belong to Users and Movies, who in turn have many reviews

Run Migrations

With the models created, we can run $ rake db:migrate to create our database.

Enable Sessions

Since we want to allow users to log in and out of our app, we have to enable sessions in the ApplicationController.

sinatra_crud_sessions.PNG
Don't forget to set your SESSION_SECRET!

Update Config.ru

Each controller you generate will automatically be added to the config.ru file, but you'll need to include the Rack::MethodOverride middleware if you want to use any HTTP methods other than get and post. Additionally, if you're using sessions in your testing, you'll need to include RackSessionAccess::Middleware.

sinatra_crud_config_ru.PNG
/config.ru

Build Routes / Views

Now the fun part. If you're taking a TDD approach as I did, this is where you'll want to start writing tests if you haven't already. Since we have all our relationships defined, we now get to create the actual behavior of our application. Start by picking a single action, such as registering a new user, and building out all the endpoints that would need to exist for that action to be completed.

In order for a user to sign up, we'll need:

  • a new user form
  • a '/signup' route that responds to get requests
  • a '/users/signup' view that loads the new user form
  • a '/signup' route that responds to post requests

A simple form can be built in the views/users/signup.html.erb file (renamed from users/new.html.erb):

sinatra_crud_signup_form
User registration form

and the routes can be added to the UsersController:

sinatra_crud_basic_signup.PNG
Basic /signup endpoints

As you build out your application, you'll find that your routes necessarily become more robust as you develop the need to validate input or redirect users under certain conditions.

sinatra_crud_advanced_signup.PNG
 More robust /signup endpoints

From here you should continue choosing actions that are missing from your app and implementing them as needed. In this domain, for example, we'll need to allow users to create, read, update, and delete (CRUD!) reviews, add new movies, and log in and out. After that, we can spend some time designing and developing the front-end, connect our app to a third-party API, or add any number of new features. 

Watch the entire development process on YouTube, or view the source on GitHub.


  Faking Data - Seeding your database with mock objects|Ruby on Rails Web App pt 1 - Models & Migration