Consider this route:
get "profile" => "pages#profile"
As you can guess, when the Rails application receives a request on the /profile
page, it will direct that request to the profile
method on the PagesController
class.
At the same time, Rails provides the controller and action name in a hash called params
in the controller.
# controllers/pages_controller.rb
class PagesController < ApplicationController
def profile
puts params # {"controller"=>"pages", "action"=>"profile"}
end
end
The main use of the params
hash is to access the user-submitted information, such as query string parameters in the URL or the form data when the user submits the form.
Dynamic Segments
So far, we've seen static URLs, such as /posts
, /about
, and /profile
. However, often your application URLs may contain dynamic content, such as /posts/20
, /users/2
, or /articles/learn-ruby
, where the numbers 20, 2, and the text learn-ruby
can vary depending on what resource the user is trying to access.
If your routes have this kind of dynamic content, i.e. parts of the URL that can vary, the Rails routing system lets you define them in the route, and make them available in the params
hash in the controller.
You can make a route dynamic by providing segment keys in the URL pattern. Consider the following route with two dynamic segments, :section_name
and :slug
.
get 'section/:section_name/article/:slug', to: 'articles#show'
Now consider what will happen when you visit the URL localhost:3000/section/rails/article/activerecord.
Rails will extract the values of dynamic segments :section_name
and :slug
, that is, rails
and activerecord
respectively; and make them available in the params
hash:
# controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
puts params
end
end
# Output
params = {
section_name: "rails",
slug: "activerecord
# ... other information such as controller and action name
}
Now in your controllers, you can read these dynamic segments to generate and dispatch appropriate response, i.e. an article on ActiveRecord under the Rails section.
To generate the URL, you have to provide the values for the segment keys. For example, given this route:
get "songs(/:genre)", to: "songs#index", as: "songs"
Calling songs_path(genre: "pop")
in your application will generate the path "/songs/pop"
.
Optional Dynamic Segments
You can also make your dynamic segments optional by wrapping them in parenthesis. For example,
get 'songs(/:genre)', to: 'songs#index'
This route will match both /songs/happy
and /songs
and will be routed to the index
action on the SongsController
class.
If you want to provide default values for the dynamic segments, you can do so by providing the :defaults
option.
get "songs(/:genre)", to: "songs#index", defaults: { genre: "rock" }
When the user visits songs/pop
, the params[:genre]
will be pop
. However, if they visit only /songs
, the params[:genre]
will be rock
.
Segment Constraints
Sometimes you may want to add some constraints on the dynamic segments in a route. For example, you may want to restrict the id
to three digits. For this, you can pass the :constraint
option as follows:
get 'images/:id', to: 'images#show', constraints: { id: /\d{3}/ }
This route would match paths such as /images/293
, but not /images/xyz
.
The above route can be succinctly expressed by passing the segment key itself.
get 'photos/:id', to: 'photos#show', id: /\d{3}/
Query Strings
A query string is indicated by the first ?
in the URL. It's used to pass additional data to the server.
http://example.com/admin?true
Rails allows you to handle query strings in a similar way to dynamic segments: by making them accessible in the params
hash.
Consider the following route:
get 'photos/:id', to: 'photos#show'
If the user agent sends an HTTP request to the photos/1?hue=10
, the params hash will contain:
params = {
id: 1,
hue: 10,
# ...
}
That's a wrap. I hope you found this article helpful and you learned something new.
As always, if you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I reply to all emails I get from developers, and I look forward to hearing from you.
If you'd like to receive future articles directly in your email, please subscribe to my blog. Your email is respected, never shared, rented, sold or spammed. If you're already a subscriber, thank you.