Key Takeaways
- Sinatra, a web application library in Ruby, provides a range of helper methods that simplify common web development tasks, including generating URLs, redirecting to other pages, and stopping a request in its tracks.
- The ‘enable’ and ‘disable’ methods can be used for app-wide settings, with a handy helper method created for any boolean settings to easily check if they are true.
- The ‘halt’ and ‘pass’ methods control the HTTP request cycle, with ‘halt’ stopping a request immediately and ‘pass’ passing the method down the chain to the next matching route.
- Other useful methods include ‘Request.xhr?’ to check if a request was made using Ajax, ‘redirect back’ to return the user to the page they came from, and ‘splat’ to create named parameters in the route definition.
Enable and Disable
You can make app-wide settings (or module-wide settings if you’re using a modular-style app) easily in Sinatra using theset
method:
set :title, "My Amazing Blog"
set :comments, true
set :tags ,false
But if the setting is a boolean value, you can use the enable
and disable
methods instead. This not only uses less code, but also reads much better.
enable :comments
disable :tags
You can also use this for built-in settings:
enable :logging
enable :sessions
Sinatra also creates a handy helper method for any boolean settings to help check if they are true. Basically it’s the name of the setting followed by a question mark. This allows us to write easy to read and follow code that checks if a settings is true or not:
if settings.comments? then display @page.comments
redirect to('/') unless settings.?
Which Environment
The following methods make checking which environment is being used a cinch:production?
development?
test?
This means you can write some nice looking conditional statements, such as:
require 'sinatra/reloader' if development?
run! unless test?
Halt and Pass
These two methods can be used in route handlers to control the HTTP request cycle.halt
will stop a request in its tracks, with an optional message or view and status code. It can be used if a process is taking too long or a critical error has occurred. Other uses include if somebody is trying to view an unauthorized page.
get '/important-process' do
halt 500 if something_bad_happened?
"Everything is okay"
end
get '/secret-page' do
halt 401,"This page is secret" unless logged_in?
"For your eyes only"
end
The pass
method can be used to pass the method down the chain to the next matching route. In the example below we have a standard route that says hello, but if the name entered in the URL is ‘daz’ then I want to pass the request on to the more specific route handler that will display a much nicer message:
get '/:name' do
pass if params[:name] == 'daz'
"Hello, #{params[:name]}"
end
get '/daz' do
"Well hello there DAZ!"
end
Of course in the example above it would just be easier to change the order of the route handlers, but there may be instances where you don’t have control over this.
Request.xhr?
If you want to know if a request was made using Ajax, then theRequest.xhr?
helper method comes in handy. This will return true if the XML HTTP Request object was used. I often use this to do redirect if Ajax wasn’t used, like in the example below which is used to delete a page. If Ajax is used then the page will just be deleted and we want the user to stay on the ‘/pages’ page, but if Ajax isn’t used then we will have to manually redirect them back to the ‘/pages’ page:
delete '/page/:id' do
page = Page.get params[:id]
page.destroy
redirect to('/pages') unless request.xhr?
end
Redirecting Back
If you have a route handler that basically performs an operation and then sends the user back to the page they came from then theback
helper method is just what you need to make you code read nicely. Used along with the redirect helper method this will simply send the user back to the page from whence they came. For example, the delete page route handler that we saw :
delete '/page/:id' do
page = Page.get params[:id]
page.destroy
redirect back unless request.xhr?
end
Splats
In Sinatra you can can create named parameters by placing a colon in front of them in the route definition, like so:get '/hello/:name' do
end
This will store whatever is entered in the place of :name in params[:name]
. We can be more general than this and use * in the route. This allows any amount of text to be entered. It is accessible through params[:splat], for example:
get '/goodbye/*/hello/*' do
end
The URL ‘/goodbye/shoes/hello/flipflops’ would give params[:splat] = [“shoes”,”flipflops”]
You can also use it with block parameters if you don’t like using the the word splat. This also makes your code more readable and self-explanatory:
get '/*.*' do |path,ext|
end
In the example above, the route ‘/application.js’ would result in variables path = 'application'
and ext = 'js'
, which could then be used inside the route handler block.
You can also use the splat to grab urls of indeterminate length:
get '/blog/ *' do |path|
@page = Page.first(:slug => path.first)
end
In the example above the route entered after ‘/blog’ can be accessed using path.first
. For example, a route such as ‘/blog/all/about/sinatra’, would result in path.first = '/all/about/sinatra'
. This can be useful when dealing with things like pretty URLs.
Cache Control
You can control how pages are cached by setting the headers directly, but there are also thecache_control
, expires
, last_modified
and etag
helpers that make cache control a piece of cake.
For example, if you had a page model in a simple CMS system, you could use the following:
get '/page/:id'
@page = Page.get(params[:id])
last_modified @page.updated_at
etag @page.content
markdown @page.content
end
For quick and dirty cache control for all pages, you can use the application start time to set the last_modified
and etag
headers globally. While the application start time may not strictly be the actual time all the files were last modified, we can usually assume that if the application has been restarted then something must have changed. In this case, It’s worth flushing the cache out and reloading the pages anyway. To set the application start time, place the following code in a configure block:
configure do
set :start_time, Time.now
end
This works because the code in a configure block is only run once at start up. Now we can use this setting to set the last_modified
and etag
headers. The settings is a Time
object, so it is fine to use for the last_modified
header, but it will need to be converted to a string in order to be used for the etag
header. If the following code is placed in a before block then it will be applied to all pages:
before do
last_modified settings.start_time
etag settings.start_time.to_s
cache_control
end
Now you should get a 304 status code instead of 200 if you refresh a page that hasn’t been modified. This is a useful way of reducing the load on the server in an application by avoiding any needless round trips to the server.
That’s All Folks
What all these methods do is make the code much easier to read and maintain. If you look at some of the code samples above, they read almost like a full sentence of English and make it very obvious what is being done. These methods also let you perform neat tricks and use less code. This is the beauty of using Sinatra – the code is short and sweet. Most of these helper methods are covered in more detail in the book. Have you used any of these and found them useful, have I missed any? Leave your answers in the comments below.Frequently Asked Questions (FAQs) about Sinatra’s Little Helpers
What are Sinatra’s Little Helpers and how do they work?
Sinatra’s Little Helpers are a set of helper methods provided by the Sinatra web application library in Ruby. They are designed to simplify common tasks in web development, such as generating URLs, escaping HTML, or redirecting to another page. These helpers are automatically included in every Sinatra application and can be used directly in your routes and views. They are designed to be intuitive and easy to use, making your code cleaner and more readable.
How can I use the ‘url’ helper in Sinatra?
The ‘url’ helper is used to generate absolute URLs in your Sinatra application. This is particularly useful when you’re creating links in your views. Here’s an example of how you can use it:get '/example' do
"<a href=\"#{url('/other')}\">Other page</a>"
end
In this example, the ‘url’ helper generates the absolute URL for the ‘/other’ route.
How can I use the ‘redirect’ helper in Sinatra?
The ‘redirect’ helper is used to redirect the user to a different route or URL. This is often used in form submissions, where you want to redirect the user after they’ve submitted the form. Here’s an example:post '/form' do
# Process the form data...
redirect '/thanks'
end
In this example, after the form data is processed, the user is redirected to the ‘/thanks’ route.
What is the ‘halt’ helper and how can I use it?
The ‘halt’ helper is used to immediately stop a request and return a specific response. This is useful when you want to return an error or stop processing due to certain conditions. Here’s an example:get '/admin' do
halt 403 unless admin?
# Continue processing...
end
In this example, if the ‘admin?’ method returns false, the request is immediately halted and a 403 Forbidden response is returned.
How can I use the ‘erb’ helper to render views in Sinatra?
The ‘erb’ helper is used to render views using the ERB (Embedded Ruby) template system. You can use it in your routes to render a view and return it as the response. Here’s an example:get '/hello' do
@name = 'World'
erb :hello
end
In this example, the ‘erb’ helper renders the ‘hello.erb’ view, passing in the ‘@name’ instance variable.
What is the ‘params’ helper in Sinatra?
The ‘params’ helper is a hash that includes both the query string parameters and the POST parameters. It allows you to access the parameters sent with the request. For example:get '/hello' do
"Hello, #{params[:name]}!"
end
In this example, the ‘params’ helper is used to access the ‘name’ parameter from the query string.
How can I use the ‘session’ helper in Sinatra?
The ‘session’ helper is a hash that you can use to store data between requests. This is often used for things like user authentication. Here’s an example:enable :sessions
get '/login' do
session[:user_id] = User.authenticate(params[:username], params[:password])
redirect '/dashboard'
end
In this example, the ‘session’ helper is used to store the authenticated user’s ID.
What is the ‘content_type’ helper in Sinatra?
The ‘content_type’ helper is used to set the Content-Type header of the response. This tells the client what type of data you’re sending back. For example:get '/data.json' do
content_type :json
{ message: 'Hello, World!' }.to_json
end
In this example, the ‘content_type’ helper is used to set the Content-Type to ‘application/json’.
How can I use the ‘request’ helper in Sinatra?
The ‘request’ helper is an object that encapsulates the HTTP request made by the client. It provides methods to access the request headers, the request method, the request URL, and more. For example:get '/example' do
"You're using #{request.user_agent}"
end
In this example, the ‘request’ helper is used to access the User-Agent header of the request.
What is the ‘settings’ helper in Sinatra?
The ‘settings’ helper is an object that provides access to the configuration settings of your Sinatra application. You can use it to access the settings defined with the ‘set’ method. For example:set :title, 'My App'
get '/example' do
"Welcome to #{settings.title}"
end
In this example, the ‘settings’ helper is used to access the ‘title’ setting.
Darren loves building web apps and coding in JavaScript, Haskell and Ruby. He is the author of Learn to Code using JavaScript, JavaScript: Novice to Ninja and Jump Start Sinatra.He is also the creator of Nanny State, a tiny alternative to React. He can be found on Twitter @daz4126.