
To understand the Rails Router API, it's essential to learn the match method, which forms the core of the Router DSL. All helper methods like get and post use match under the hood. Additionally, most of the shorthand syntax such as scopes and constraints use the options provided by match behind the scenes.
In its essence, the match method matches a URL pattern to one or more routes. Here's the basic API of the match method, which is defined inside the Mapper class.
# actionpack/lib/action_dispatch/routing/mapper.rb
def match(path, options = nil)
endThe first parameter path tells the router what URL pattern you wish to match. It can be either a String or a Hash.
- The string version specifies the URL pattern, e.g.
/posts/publish/:id - The hash matches the URL pattern to a
controller#actionpair, like"/posts/1" => "posts#show".
The second parameter options is a hash containing additional data required by the router to decide where it should redirect this request. You can also pass any custom data, which gets passed to the params hash accessible in the controllers.
Here are some usage examples of the match method.
match 'photos/:id' => 'photos#show', via: :get
match 'photos/:id', to: 'photos#show', via: :get
match 'photos/:id', controller: 'photos', action: 'show', via: :getAll the three routes above do the same thing, dispatch the HTTP GET request at /photos/:id to the show action method on the PhotosController class.
In its simplest and most explicit form, you supply a string URL pattern along with the name of the controller and the action via options.
match "photos/:id", controller: "photos", action: "show", via: :getIf you don't want to pass them separately, a string in the form of controller#action is also allowed with the :to option.
match "photos/:id", to: "photos#show", via: :getFinally, the hash version simplifies this even further:
match "photos/:id" => "photos#show", via: :getMatching Multiple HTTP Verbs
As we'll learn later, you'll often use shortcuts like get and post instead of directly using the match method. However, match comes in handy when you want to match a route for multiple HTTP verbs.
match "photos/:id", to: "photos#handle", via: [:get, :post]Note: the :via option is mandatory for security-related reasons. If you don't pass it, the router raises an ArgumentError.
Options Available to Match Method
The options hash helps the router identify the action to which it should pass the incoming request. Here are some of the important options that you can provide to the match method.
params hash, which you can access in the controllers, using the params hash.:controller and :action
The controller and action keys are used together. They specify the name of the controller and the action you want to route this request to.
match "home", controller: "application", action: "home", via: :get:to
If you don't want to pass the controller and action separately, the :to option lets you pass the controller#action as a string.
match "home", to: "application#home", via: :getNote: You're not restricted to using only controller actions for incoming requests. The :to option also allows you to point to a Rack endpoint, i.e. any object that responds to a call method. This is really useful for quickly testing routes without creating new controllers, actions, and views.
match "path", to: -> (env) { [200, {}, ["Success!"]] }, via: :get
match "path", to: RackApp, via: :getTo learn more about forwarding a request to a Rack application, check out the following post:

via
Lists the HTTP verb for this route. You have to pass at least one HTTP verb, for security-related reasons.
match 'path', to: 'controller#action', via: :get
match 'path', to: 'controller#action', via: [:get, :post]
match 'path', to: 'controller#action', via: :allAlternatively, you can use the shorthand helper methods such as get, post, and so on which implicitly provide the HTTP verb.
module
Use this if you want namespaced controllers. The following route directs the request with /posts URL to Blog::PostsController#index action.
match '/posts', module: 'blog', controller: 'posts', action: 'index', via: :getas
This option provides the name for the generated URL helpers. The following route creates the helpers named blog_path and blog_url.
match 'posts', to: 'posts#index', as: 'blog', via: :getTo learn more about named routes, check out the following post:

constraints
If you want to put more restrictions on what URL patterns a route should match, provide this option with a hash of regular expressions. It can also take an object responding to matches?.
match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :getdefaults
Sets the default value for a parameter. The following route will set the value of params[:author] to 'Akshay'.
match '/courses/publish(/:author)', to: 'courses#publish', defaults: { author: 'Akshay' }, via: :getFor a complete list of options, check out the API docs for the match method. Most of the routing methods you'll use are just shorthands using various combinations of the match method's options.
param
In the resourceful routes, :id is the name of the dynamic segment used to generate the routes. The param option overrides this default resource identifier. You can access the value of this dynamic segment using param[<:param>].
resources :posts, param: :slugThe posts resource will contain :slug as the dynamic segment, e.g. posts/:slug.
To construct the URL, override the ActiveRecord::Base#to_param method.
class Post < ApplicationRecord
def to_param
title.parameterize
end
end
post = Post.find_by(title: "Ruby on Rails")
post_path(post) # "/posts/ruby-on-rails"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.
