Fiddling Around With Sinatra

Darren Jones
Darren Jones
Share
JSFiddle is a site that’s been around for a while now. It allows you to create a ‘fiddle’ which is basically a self contained page of HTML, CSS and JavaScript. These can be used to show off a particular technique or bug or just show off your smooth markup skills. In the last year, a couple more sites have appeared that do a similar thing. First there was Dabblet and just recently Code Pen was launched. I thought it might be fun to have a go at cloning this type of app in Sinatra. It should be fairly straightforward as Sinatra uses Tilt to render views. This gives you access to loads of different rendering engines, as well as Sass
and Less for CSS preprocessing. My idea is to create a simple app called Riddle (A Ruby flavored Fiddle) that allows users to create a ‘riddle’ which is basically a self-contained piece of HTML, CSS and JavaScript. To start with, I am going to limit users to using either markdown or plain old HTML for markup and SCSS or vanilla CSS for styling. Hopefully, this will help to show how Sinatra’s view helpers work and how to serve CSS and JavaScript using Sinatra.

Mock Up

I wanted to get the site architecture of the app right, so I concentrated on the views first to show how a user would navigate around the app. We want a start page that lists all the riddles that have been created and lets the user click to view one. There should also be a button at the top to create a new riddle. This should display a form where you can add the the HTML, CSS and JavaSript. Once the user clicks on save, they will be taken to the newly created view. So, let’s get coding! We need to start off by creating an empty text file called main.rb and add the following lines of code: [gist id=’3359802′] What’s going on here? This is a full Sinatra app, all in one file. First of all, we require the sinatra and slim gems. Slim is my preferred view engine, but feel free to use another (such as ERB or Haml). Next, we have the three routes that we need – index, new and show
– all of which have their own view, rendered with slim. Then, at the bottom of the page I’ve incldued those views inline (cool Sinatra feature!). The first is a standard HTML5 layout. Following the layout, there are three holding pages that just describe what that page will eventually do. Give it a try – start a server up by typing ruby main.rb into a terminal and then navigate to ‘http://localhost:4567’ to see it working. I love this about Sinatra – you can mock up the architechture of a site quickly to demonstrate how a user will navigate around the app. Using this feature, it’s simple to make sure it fits with your expectations before you start doing any of the heavy lifting. Everything is working fine, now it’s time to start create some riddles – to that, we’re going to need a database …

Creating Some Riddles

Now we have the app’s structure in place, it’s time to create the database that will hold the information about the Riddles. To do this, we first need to configure the database. I’m going to use DataMapper as the ORM, which is really easy to configure in Sinatra. Just add the following lines to the top of main.rb: [gist id=’3331618′] We need to require quite a few extra gems to get DataMapper working. This is mainly because it is quite modular by design – a good thing – as it means you can pick and choose which modules you want to include on a per project basis. We’re going to make use of the migrations module later to create the database. We also need to configure the database. This is done inside the configure block where the database used is set as an environment variable, or simply a SQLite file called ‘development.db’ in the root directory of the app. This sets us up for using Heroku for deployment later, as their databases are stored in an environment variable called ENV[‘DATABASE_URL’]. If this isn’t present, then we must be working locally, so the SQLite file will be used instead. Our next job is to create the Riddle class. [gist id=’3331622′] This is all fairly standard DataMapper stuff. You need to include the DataMapper::Resource module and then set the id
property. Next, we have the properties of each Riddle – they will have a title, some HTML, CSS and JavaScript. After this, I’ve added an extra method that sets the title to “Yet another untitled Riddle” if an empty string is entered. DataMapper has a default option, but this is no good when dealing with forms on the web because any empty fields go into the database as empty strings, rather than nil. This is one way of dealing with it. It’s really important to remember to use the DataMapper.finalize declaration at the end of all your classes. Things go badly if you don’t do this (can’t tell you how many times I’ve forgotten this!) It’s time to migrate the database. This is a simple job, all we need to do is go into a terminal and navigate to the folder where our riddle app resides and then launch an irb session:
$ irb ruby-1.9.2-p180 :001 > require './main' ruby-1.9.2-p180 :001 > DataMapper.auto_migrate! 
Now the database has been created, we need to update our routes so that we can actually create a riddle. [gist id=’3331626′] We also need to update our show view. We’re only going to display what has been saved, rather than displaying it as actual HTML, CSS and JavaScript for now, just to check that everything is working: [gist id=’3331629′] The change to the form adds a name to the form elements. These are picked up by our Sinatra application and used in the following line to create the riddle:
riddle = Riddle.create(params[:riddle]) 
Go ahead and give this a test and you’ll see that it’s working – everything is being saved to the database and then being displayed on the show
page! Before we go on, let’s just update the index page so that it lists all of the riddles that have been created in reverse order. Simply add a line to the handler to get all the riddles in reverse order: [gist id=’3331631′] Then we just need to update the index view so that it shows all the riddles (assuming there are any): [gist id=’3331633′] Brilliant! Restart the server (press control+c in the terminal then retype ruby main.rb), then have a quick look at ‘http://localhost:4567’ to see a list of all your creations so far. Now we just need to get them working properly….

Putting It All Together

Now that we know that the riddles are being saved, it’s time to think about how they are displayed. Let’s update the ‘@@show’ view so that it shows the title of the riddle and displays the HTML underneath: [gist id=”3331634″] Give this a test and it should display the HTML correctly. We can do a little better than this by utilizing Tilt to use Markdown to display the markup instead. This will allow people to use the easier markdown language. The good thing about this is thsat, if you enter just vanilla HTML, markdown will still display it. This allows the user to use choose to use either markdown or HTML. To use markdown, you need to include a library that supports it, I’m going for Red Carpet:
require 'redcarpet' 
Then all you need to do is update the show view to use the Sinatra helper to display the markup using markdown instead: [gist id=’3331636′] Give this a try – here’s some markdown you can enter as a quick test:
# Hello ## world * one * two * three 
Now that we can display the markup, it’s time to get the styles working … We’re going to insert the riddle’s styles as if it’s an actual stylesheet in the head of the document. We need to add the following line to the @@layout:
- if @riddle link rel="stylesheet" href="/css/riddle/#{@riddle.id}/styles.css" 
This checks to see if there is a @riddle object, then links to a stylesheet that includes the id of the riddle. This stylesheet doesn’t actually exist as an actual file – it’s in the database – but we can fetch it as if it is by using Sinatra’s cool and simple routing mechanism: [gist id=’3331640′] When the link gets called, Sinatra will serve the styles held in the database using the SCSS helper. The reason I’ve used SCSS is that I’ve added the id ‘#riddle’ in front of the styles. The SCSS engine will now namespace all of the styles and place the ‘#riddle’ id in front of them all, meaning that these styles will only affect anything inside the #riddle div (notice that the HTMl markup for the riddle was placed inside a div with an id of ‘riddle’ in the show view. In other words, these styles will only affect the riddle!) Give this a quick test and you should find it working as expected. What’s cool is this looks like it’s a link to an external stylesheet – you can even view the styles by going to ‘http://localhost:4567/css/riddle/9/styles.css’. It also means that the user can choose to use plain CSS or SCSS. Last of all, let’s get the JavaScript working. In a similar way to the CSS, we’re going to make this look like it’s coming from an external file, so we need an extra line in the @@layout:
- if @riddle link rel="stylesheet" href="/css/riddle/#{@riddle.id}/styles.css" script src="/js/riddle/#{@riddle.id}/script.js" 
This will load a script that refers to the riddle’s id if a @riddle object exists. Now we just need the handler to deal with this: [gist id=’3331642′] We need to do a bit more here. Earlier, when we were displaying the styles, Sinatra knew that the content type was a stylesheet because we were using the SCSS helper. This time we need to declare explicitly that the file is JavaScript. We also need to make sure that the layout isn’t used again. Give this a test and it should be working great. In no time at all, we’ve managed to build a way of creating pages using HTML, CSS and JavaScript. As an added bonus, it supports markdown and SCSS out of the box! And all of this in just over 100 lines of Ruby code! But we can do more! In the next part I’m going to ramp things up by unleashing the full force of Tilt and letting the user choose any of the view engines … including CoffeeScript! I’ll also include the ability to edit Riddles after they’ve been created. Hope to see you soon in part 2!

Frequently Asked Questions (FAQs) about Sinatra and Fiddling Around

What is Sinatra and how does it differ from other web application libraries?

Sinatra is a Domain Specific Language (DSL) for quickly creating web applications in Ruby. It’s a lightweight and flexible library that provides a minimalistic approach to web development. Unlike other web application libraries like Rails, Sinatra doesn’t follow the Model-View-Controller (MVC) pattern. Instead, it focuses on simplicity and speed, making it an excellent choice for small applications or microservices.

How do I get started with Sinatra?

To get started with Sinatra, you first need to install the Sinatra gem. You can do this by running the command ‘gem install sinatra’ in your terminal. Once installed, you can create a new Ruby file and require ‘sinatra’ at the top. From there, you can define routes and start building your web application.

What does ‘fiddling around’ with Sinatra mean?

Fiddling around’ with Sinatra refers to the process of experimenting, learning, and playing with the Sinatra library. It’s about exploring its features, understanding how it works, and figuring out how to use it effectively to build web applications.

How do I define routes in Sinatra?

In Sinatra, routes are defined by specifying the HTTP method and the URL pattern. For example, to define a route for the homepage, you would write ‘get ‘/’ do’ followed by the code to execute when the route is matched. This could be rendering a view, returning a string, or any other action.

Can I use Sinatra to build large applications?

While Sinatra is best suited for small applications and microservices due to its simplicity and minimalism, it’s possible to build larger applications with it. However, as the complexity of the application increases, you might find that a more structured framework like Rails is more suitable.

How do I handle errors in Sinatra?

Sinatra provides several ways to handle errors. You can use the ‘error’ method to define custom error pages, or the ‘halt’ method to immediately stop a request and return a specific response.

Can I use Sinatra with a database?

Yes, you can use Sinatra with a database. Sinatra doesn’t come with built-in database support like Rails, but you can easily integrate it with libraries like ActiveRecord or DataMapper to interact with a database.

How do I test my Sinatra application?

You can test your Sinatra application using testing libraries like RSpec or MiniTest. Sinatra also provides a ‘test’ method that you can use to simulate requests to your application and check the responses.

Can I use Sinatra to build RESTful APIs?

Yes, Sinatra is an excellent choice for building RESTful APIs. Its simplicity and flexibility make it easy to define routes that correspond to the different HTTP methods used in RESTful APIs.

How do I deploy my Sinatra application?

There are several ways to deploy a Sinatra application. You can use a platform like Heroku, which simplifies the deployment process, or you can manually set up a server and deploy your application using a tool like Capistrano.