15
How does Params work in Sinatra?
When working with Sinatra or Rails, you will most likely encounter something called params. It is short for parameters and is often seen inside route (request handler) blocks of controllers that handle HTTP requests such as GET or POST:
# songs_controller.rb
patch "/songs:id" do
song = Song.find(params[:id])
attrs_to_update = params.select{|k,v| ["name", "genre"].include?(k)}
song.update(attrs_to_update)
song.to_json
end
At first, params
may seem a bit magical as it somehow automatically contains the data included in requests:
params = {
"name" => "some_name",
"genre" => "some_genre",
"id" => "some_id"
}
So what is this magic called params
?
Params is a method inherited from ActionController::Base
that accesses the parameters passed from a request and returns a hash that encapsulates the parameters. It can access those parameters in one of two main ways: through the request body or through the request path.
Oftentimes, a web application will have an HTML form that can be filled by the user. On submission, the form would typically generate a POST request that contains the values of the user's inputs along with the names of the inputs inside a body object:
// A POST request that contains a body object
const newSong = {
name: "Fly Me to the Moon",
genre: "Jazz"
}
const configObj = {
method: "POST",
headers: {
"Content-Type": "applications/json",
"Accept": "applications/json"
},
body: JSON.stringify(newSong)
};
fetch("http://example.com/songs", configObj);
When this request is received by the controller, it will look at the body object sent with the request and add parameters accordingly to the params
hash:
params = {
"name" => "Fly Me to the Moon",
"genre" => "Jazz"
}
Note: The keys and values of a
params
hash will always be of the string type. However, the hash keys can be accessed indiscriminately as strings or symbols sinceparams
doesn't actually return a hash, but it returns something similar calledSinatra::IndifferentHash
.
The other main way to access request parameters is through the request path, or simply the URL. When the controller receives the request, it will look at the attributes within the request URL and add parameters to the params
hash based on those attributes. This allows us to design routes more dynamically instead of hard-coding each route individually. There are two types of parameters that can be accessed based on the URL attributes: query and route parameters.
Query parameters are parameters included after the ?
in the request URL as shown below:
// A GET request with query parameters in the URL
fetch(http://www.example.com/songs?name=foo&genre=pop)
Such parameters are often used when we want to filter our search results (AKA what a GET request returns) by some queries and restrictions. For this reason, query parameters are considered optional and not explicitly included in the route path:
# songs_controller.rb
get "/songs" do
...
end
However, the params
hash will still include the query parameters found in the request path:
params = {
"name" => "foo",
"genre" => "pop"
}
Unlike query parameters, route parameters must be named within the route path for them to be accessible via the params
hash:
# songs_controller.rb
get "/songs/:id" do
...
end
The controller would then recognize the route parameter in the request path by the placement of the parameter value within the URL:
fetch("http://www.example.com/songs/3")
... and add it to the params
hash:
params = { "id" => "3" }
Route parameters can also be combined with query parameters:
fetch("http://www.example.com/songs/3?name=foo&genre=pop")
... for an even more customizable params
hash:
params = {
"id" => "3",
"name" => "foo",
"genre" => "pop"
}
While the magic of params
is often unquestioned and left to wonders, its behavior under-the-hood is actually straightforward to grasp. To summarize, params
is an inherited method that returns a hash that contains parameters passed by a request through its body or through its URL. Overall, understanding this behavior will (hopefully) make your life easier by equipping you with the ability to control the structure of the params
hash as well as build routes more effectively.
Params can also access other types of parameters such as splat (wildcard), regular expression (regex), and optional parameters. To learn more about them, you can refer to the first resource down below.
Happy coding!
15