Skip to content

Rails error: Routing Error: No route matches

Sean Lerner edited this page Apr 12, 2017 · 3 revisions

If your error looks like ...

Routing Error
No route matches [GET] "/product/5"

Rails.root: /Users/sean/Desktop/product_app

... then either your URL is incorrect, or you need to define the route.

How To Fix

Step 1: Match the Path of your URL to your routes

When a routing error is raised, rails will also show you your routes on the page, like so:

Routes

Routes match in priority from top to bottom

Helper HTTP Verb Path Controller#Action
products_path GET /products(.:format) products#index
POST /products(.:format) products#create
new_product_path GET /products/new(.:format) products#new
edit_product_path GET /products/:id/edit(.:format) products#edit
product_path GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy

Take a look at your URL (in your browser's location bar), and try to match it against the Path column.

You can ignore the (.:format) part of the Path if you're doing a regular http request.

You can reproduce your routing table on the command line by issuing:

rails routes

Figure out your Path by looking at your URL. For example, if I have the following in my browser's location bar:

http://localhost:3000/product/5

... then the path would be product/5.

Now look at the paths in your routing table and try to match it against the path in your URL.

When matching against a Path in your routing table, break the pattern into segments, with each segment being in between two slashes. For example:

/products/new - products is one segment, new is another segment.

Figure out if each segment is a static or dynamic segment:

  • static segments do not begin with a : (colon)
  • dynamic segments begin with a : (colon)

Match each segment with your URL's path:

  • static segments need to match exactly
  • dynamic segments are wildcards, and can match against anything

Step 2: Determine if you need to define a route

If your URL is correct, but there's no route to match it against, then you need to define a route.

Open up config/routes.rb and configure the route.

If this is a standard CRUD resource, then simply add:

resources :products

to your routes. (replacing products with the name of your resource). Ensure your resource is pluralized.

If you just need a single route, you can define it like so:

get 'products/:id' => 'products#show'

Replacing:

  • get with the http request method
  • 'products/:id' with the pattern to match against
  • 'products#show' with the controller and action (method)

For more details on routing, see the rails guide Rails Routing from the Outside In.

Step 2: Determine if your URL is correct

Perhaps you have the proper routes defined, and it's your URL that isn't correct.

For example, if I take:

http://localhost:3000/product/5

... and compare it to the routing table in the previous step, I notice that an s is missing in my URL. It should be:

http://localhost:3000/products/5

Often it's the case you'll be using link_to along with a URL or Path helper (methods that end with _url and _path).

The _url and _path helpers are generated from your routes.rb file. You can see what helpers are available by running

rails routes

from your command line.

For example, if you see:

$ rails routes
      Prefix Verb   URI Pattern                  Controller#Action
    products GET    /products(.:format)          products#index
             POST   /products(.:format)          products#create
 new_product GET    /products/new(.:format)      products#new
edit_product GET    /products/:id/edit(.:format) products#edit
     product GET    /products/:id(.:format)      products#show
             PATCH  /products/:id(.:format)      products#update
             PUT    /products/:id(.:format)      products#update
             DELETE /products/:id(.:format)      products#destroy

and looking at the Prefix column. In the example above, the following methods are available:

products_path
products_url
new_product_path
new_product_url
edit_product_path
edit_product_url
product_path
product_url

The arguments (if any) you pass to these methods are determined by the number of dynamic segments in the URI Pattern.

For example, the following route:

products GET    /products(.:format)          products#index

does not have any dynamic segments, so no argument would be passed to the products_path and products_url methods. You might use this helper in a view like so:

link_to('View All Products', products_path)

In this example:

product GET    /products/:id(.:format)      products#show

There is one dynamic segment :id, so you need to pass one argument to the product_path and product_url method. You might use this helper in a controller like so:

redirect_to product_path(@product)

If you're using nested routing and you have multiple dynamic segments, you need to pass a value for each dynamic segment within an array. For example, if you have the following route:

store_product GET    /stores/:store_id/products/:id(.:format)      products#show

then you're working with two dynamic segments (:store_id and :id). For example, you might use the path helper like so:

# In a view:
link_to("View info on #{@product.name}", store_product_path([@store, @product]))

# In a controller:
redirect_to store_product_path([@product.store, @product])

More info:

Clone this wiki locally