DEV Community

loading...
Cover image for How does Params work in Sinatra?

How does Params work in Sinatra?

Anthony Chung
Aspiring full-stack software engineer looking for work. With my prior experience in materials science and bioengineering, I am proud to be a well-rounded, full-time nerd 🤓
・3 min read

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 
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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.

Accessing Parameters Through the Request Body

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);
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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 since params doesn't actually return a hash, but it returns something similar called Sinatra::IndifferentHash.

Accessing Parameters Through the Request Path

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

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

However, the params hash will still include the query parameters found in the request path:

params = {
   "name" => "foo",
   "genre" => "pop"
}
Enter fullscreen mode Exit fullscreen mode

Route Parameters

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
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

... and add it to the params hash:

params = { "id" => "3" }
Enter fullscreen mode Exit fullscreen mode

Route parameters can also be combined with query parameters:

fetch("http://www.example.com/songs/3?name=foo&genre=pop")
Enter fullscreen mode Exit fullscreen mode

... for an even more customizable params hash:

params = {
   "id" => "3",
   "name" => "foo",
   "genre" => "pop"
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

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!

Resources

Discussion (0)