Skip to content
By Tianwen Chen

Rails Discovery: Magical Routes - Part 1: Major Usages

NOTE: The Rails version for this article is v3.2.17. The content might not be applicable to other Rails version.

NOTE: Before we dig into the Rails routing, if you are not familiar with it, please have a read on Rails Guides: Rails Routing from the Outside In.

In this article, we will talk about three different ways to generate URLs used by Rails among controllers, mailers, views and helpers. There will be examples and some suggestions on when you should use them.

1. Named route path helper

As in most of the Rails app, you might see the following snippet:

<%= link_to edit_post_path(@post, source: 'external'), 'Edit' %>

When it is rendered, it will generate the following HTML:

<a href="/posts/1/edit?source=external">Edit</a>

The edit_post_path is a registered helper method and the edit_post is called a named route. Most Rails devs should be familiar with this as one of the Rails conventions, but especially for beginners, how does it work? We will find out in the next article.

Before that, let's take a look at how to find out all of the named routes. Run the following command in your terminal:

orz $ bundle exec rake routes

It will print a list of named routes that are available inside controllers, mailers, views and helpers.

                    Prefix Verb   URI Pattern                            Controller#Action
                     posts GET    /posts(.:format)                       posts#index
                           POST   /posts(.:format)                       posts#create
                  new_post GET    /posts/new(.:format)                   posts#new
                 edit_post GET    /posts/:id/edit(.:format)              posts#edit
                      post GET    /posts/:id(.:format)                   posts#show
                           PATCH  /posts/:id(.:format)                   posts#update
                           PUT    /posts/:id(.:format)                   posts#update
                           DELETE /posts/:id(.:format)                   posts#destroy

OR open this link in the browser to view a similar output from the local rails server http://localhost:3000/rails/info/routes

NOTE: This routes link is ONLY visible in the development environment.

Prefix

Prefix column lists the unique named routes. Normally, the named route together with a suffix _path or _url forms a helper method, e.g. new_post_path

NOTE: By appending _url, the named route path helper will generate a full URL, e.g. new_post_url => http://localhost:3000/posts/new, whereas appending _path will just generate the site-relative URL, e.g. new_post_path => /posts/new.

Verb

Verb column specifies the HTTP request method for a route. Generally, the acceptable HTTP request methods for Rails are GET, POST, PATCH, PUT and DELETE. (see constant HTTP_METHODS on ActionDispatch::Request for more details )

URI Pattern

URI Pattern column shows the URI pattern that Rails uses to match a route. Symbols will be mapped into the params helper method. For instance, for URI pattern /posts(.:format), the json of URI /posts.json will be stored in params[:format].

Controller#Action

Controller#Action column shows the corresponding controller and action to which Rails will dispatch the HTTP request.

When / Where should I apply this?

If you know exactly what the path or URL is that you are going to generate, you should use the named route path helper methods. By using it, your code will become more readable.

2. URL helper method

ActionDispatch::Routing::UrlFor#url_for is the URL helper method. It generates a URL based on the options supplied. It is pretty flexible in that it accepts either a string, an ActiveRecord object, an options hash, or an argument list array.

Let's take a glimpse at some examples and see how powerful it is.

Examples

url_for('/posts')
# => /posts

url_for(@post)
# => http://localhost:3000/posts/1

url_for(controller: :comments, post_id: @post.id)
# => http://localhost:3000/posts/1/comments

url_for([@post, :comments])
# => http://localhost:3000/posts/1/comments

url_for([@post, routing_type: :path])
# => /posts/1

url_for([@post, :comments, slug: 'reinteractive', only_path: true])
# => /posts/1/comments?slug=reinteractive

url_for([:admin, :posts, format: :js])
# => http://localhost:3000/admin/posts.js

It accepts the following hash options, you could find this in the API document #url_for:

Options for URL helper method

  • :only_path - If true, the relative url is returned. Defaults to false.
  • :protocol - The protocol to connect to. Defaults to 'http'.
  • :host - Specifies the host the link should be targeted at. If :only_path is false, this option must be provided either explicitly, or via defaulturloptions.
  • :subdomain - Specifies the subdomain of the link, using the :tld_length to split the subdomain from the host. If false, removes all subdomains from the host part of the link.
  • :domain - Specifies the domain of the link, using the :tld_length to split the domain from the host.
  • :tld_length - Number of labels the TLD id composed of, only used if :subdomain or :domain are supplied. Defaults to ActionDispatch::Http::URL.tld_length, which in turn defaults to 1.
  • :port - Optionally specify the port to connect to.
  • :anchor - An anchor name to be appended to the path, as in "/archive#2009"
  • :trailing_slash - If true, adds a trailing slash, as in "/archive/2009/"
  • Any other key (:controller, :action, etc.) given to url_for is forwarded to the Routes module.

Additionally, you might come across this option in the source code:

  • :routing_type - Specifies which type of URL it should be, relative or full. Value can be :url or :path. Defaults to :url.

When / Where should I apply this?

The url_for method is useful when you require flexibility. Consider the following situations:

  • Passing variable ActiveRecord objects to the helper, e.g. url_for(@post_or_comment)
  • Specifying variable options (:controller, :action, :anchor, etc.), e.g. url_for(controller: @posts_or_comments_controller)
  • Specifying the URL string, e.g. url_for('/posts')

You will find this helper very useful.

3. Polymorphic URL helper methods

ActionDispatch::Routing::PolymorphicRoutes#polymorphic_path and ActionDispatch::Routing::PolymorphicRoutes#polymorphic_url are the polymorphic URL helpers which can handle either an ActiveRecord object, an options hash, or an Array. Under the hood, polymorphic_url is called by url_for, and both polymorphic_path and polymorphic_url can be prefixed with new_ and edit_. In other words, the polymorphic URL helpers wrap the url_for method to provide better object support, although they can't handle plain strings.

Examples

polymorphic_path(@post)
# => /posts/1

polymorphic_url([@post, @comment])
# => http://localhost:3000/posts/1/comments/1

edit_polymorphic_path(@post)
# => /posts/1/edit

new_polymorphic_path(:post)
# => /posts/new

NOTE: The options for URL helper method are also applicable for polymorphic URL helper methods.

Polymorphic URL helper methods are very powerful and they've been used in a lot of places throughout rails, e.g. ActionView::Helpers::UrlHelper#link_to, ActionView::Helpers::FormHelper#form_for, ActionController::Redirecting#redirect_to (see ActionDispatch::Routing::PolymorphicRoutes)

When / Where should I apply this?

Similar to url_for, the situations where polymorphic urls are very useful are when you have a dynamic argument. Imagine you had a homepage where you wanted an edit link for the latest post or the latest comment by the current user in a sidebar. You could call the method like this:
edit_polymorphic_url(@post_or_comment). In this case it would also be trivial to check the class of the object, but that approach becomes unwieldy when you have more than just a couple of classes to consider.

When building an engine or a gem that abstracts functionality without necessarily knowing which classes it is working with, helpers like this will help immensely to keep your code clean.


We will continue to explain how the named routes works in next article Part 2

Latest Articles by Our Team

Our expert team of designers and developers love what the do and enjoy sharing their knowledge with the world.

We Hire Only the Best

reinteractive is Australia’s largest dedicated Ruby on Rails development company. We don’t cut corners and we know what we are doing.

We are an organisation made up of amazing individuals and we take pride in our team. We are 100% remote work enabling us to choose the best talent no matter which part of the country they live in. reinteractive is dedicated to making it a great place for any developer to work.

Free Community Workshops

We created the Ruby on Rails InstallFest and Ruby on Rails Development Hub to help introduce new people to software development and to help existing developers hone their skills. These workshops provide invaluable mentorship to train developers, addressing key skills shortages in the industry. Software development is a great career choice for all ages and these events help you get started and skilled up.

  • Webinars

    Webinars

    Webinars are our online portal for tips, tricks and lessons learned in everything we do. Make the most of this free resource to help you become a better developer.

    Learn more about webinars

  • Installfest

    Installfest

    The Ruby on Rails Installfest includes a full setup of your development environment and step-by-step instructions on how to build your first app hosted on Heroku. Over 1,800 attendees to date and counting.

    Learn more about Installfest

  • Development Hub

    Development Hub

    The Ruby on Rails Development Hub is a monthly event where you will get the chance to spend time with our team and others in the community to improve and hone your Ruby on Rails skills.

    Learn more about Development Hub

Get the “reinteractive Review” Monthly Email