Using Sinatra and DataMapper to Build Web Apps

At the start of June I volunteered as a coach at a day long Codebar event ‘Mind the Code’.

MTC-Exercise1

(Photo: Discussing domain models with a group of Codebar students at Mind the Code)

As the title may or may not suggest, Mind the Code was a day comprised of mindfulness, coding and yoga. It was a brilliant day and of course it served as a good reminder about how breaks away from the computer can help us concentrate better and solve problems. For the main coding exercises the students had a bunch of projects that they could choose to work on, thought up by the wonderful Denise Yu who created and organised the event.

The Ruby projects all involved using Sinatra which is a Ruby framework that is alot more lightweight than Rails. I hadn’t really used it too much before due to usually working on Rails apps, so I spent a bit of time before the workshop knocking up some of the example projects (some of which can be viewed from www.rosafox.com/projects).

This post will be about using Sinatra to build a simple app in conjuction with DataMapper to manage the database.

A bit more about Sinatra

I found it was super easy to get started with Sinatra and to display a view when making a get request to a specified URL. Things then started to advance as I needed to build an application. At first I found setting up the structure a bit time consuming as I suppose rails new has made me pretty lazy. I think once you have made a couple of small apps using Sinatra you will quickly be able to knock out a basic structure that works for you.

I could see why using Sinatra may be favourable; you don’t end up generating useless excess files (which I recently heard described as ‘the monolith approach’) and you have more control over how you lay out your app. On the flip side, you have to actually think about the structure which is slightly more time consuming at first.

People had told me before that although Sinatra was good for making smaller apps, as soon as it gets bigger and you need to persist stuff into a database you end up needing to require Active Record and then it just turns into re-inacting Rails. I was kind of sceptical about this as I tried to set up my Active Record gem. For some reason I was having trouble with adding in the Active Record gem which was kind of making me lose faith in Sinatra. I was then advised not to use Active Record with Sinatra and in fact to use DataMapper and this was a revelation. I was really impressed by how easy it was to use and I really do think it makes a great alternative to Rails if you want to put together a small app.

What is DataMapper?

DataMapper is an ORM written in Ruby. It is really easy to use because you don’t have to write out separate migrations like you do with Active Record. You literally just write in or remove the names of the fields you want from within your class and they will be created or destroyed on saving your file and booting the server. So that your existing data isn’t wiped away on each save you will need to configure DataMapper so that you have DataMapper.auto_upgrade! unless you want it overwritten in which case use DataMapper.auto_migrate!

Further information can be found in the getting started guide. For an example of a basic CRUD application which uses Sinatra and DataMapper please clone my Todo app example: git clone https://github.com/Rosa-Fox/todo-sinatra-datamapper.git Looking at open source code on Github is a really useful way of figuring out which components you will need in your project own structure.

Snip20150724_1

The logic of the app is written in the server.rb file. This is also where all the routing is handled. We begin by requiring sinatra and data_mapper which allow us to make use of those gems. We also load datamapper_setup.rb. This loads the datamapper_setup.rb file. In there we set up DataMapper with a postgres db connection and tell it to auto_upgrade! so that our data is not wiped away. If you don’t want to bother with using postgres and want to stick with sqlite3 I would recommend cloning this repo and watching the video I linked in the description to the original tutorial. This is a really good example of a very bare bones, simple, right from the beginning look at using the two together so it is a brilliant place to start.

git clone https://github.com/Rosa-Fox/datamapper.git

Next in server.rb we create a class for our DataMapper todo table. We include DataMapper::Resource and then simply add the properties that we want the table to have, giving the a name and type.

Snip20150724_3

To activate the todo database table we need to start the server. In this case the server is set up to use rack so run rackup in the terminal to start the server (navigate to localhost:9292/todo to see the todos). When we 'rackup' we run the config.ru file.

Snip20150724_6

./datamapper_setup is required here. DataMapper.auto_upgrade and Data.finalize are called and thus our db table is created. We are able to query our todo table, similar to using Rails console with Active Record. Firstly open a terminal and make sure you are cd’d into the same directory that contains server.rb I am using pry (as the pry gem is added to the Gemfile and required in config.ru) but irb will work fine out of the box.

Snip20150724_2

As you can see, the queries are ever so slightly different to Active Record (get instead of find etc). Here are some more commands. Next in server.rb we then have our Sinatra code within the MindTheCodeApp class which inherits from Sinatra::Application.

The best place to get started with Sinatra is of course the Sinatra website. The code on the Sinatra homepage will get you displaying some text on a webpage served locally on port 4567 very quickly. The general idea is you write your controller style code but instead of naming the method with a conventional action and then routing, you do it all in one step and define your route before the block containing the instructions for that http action. So get ‘/todo’ is going to be called when we make a get request (aka navigate to) localhost:9292/todo. We use an instance variable @todos to pass in a collection of todos to the todo#index view. We then specify which view should be loaded using erb :’todos/index’.

Snip20150724_5

If we go to localhost:9292/todo we will see: Snip20150724_9

Overall I think Sinatra takes a little time to get used to. It is easy to require things in the wrong order and then wonder why it isn’t working and the like. Once you get over these teething problems and have built a few small apps from scratch it will be a really useful tool for building small projects, giving you more control over the structure and allowing you to develop with more of a ‘bottom up’ approach as opposed to generating a large project and deleting templates that you don’t need.