Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails route appears in routes but throws a 404

I'm trying to add a simple route to an existing controller/action but strangely I'm getting a 404 error even though the route appears to exist.

Here's the relevant section of my routes.rb:

  # Wines
  scope 'wine' do
    get '/',                  to: 'wines#index',              as: 'wine_index'
    get '/:collection',       to: 'wines#collection_detail',  as: 'collection_detail'
    get '/:collection/:slug', to: 'wines#wine_detail',        as: 'wine_detail'
    get '/:style',            to: 'wines#style_detail',       as: 'style_detail'
  end

It seems correct because here's what I see when I check:

$ rake routes
=>

            Prefix Verb     URI Pattern                                              Controller#Action

        wine_index GET      /wine(.:format)                                          wines#index
 collection_detail GET      /wine/:collection(.:format)                              wines#collection_detail
       wine_detail GET      /wine/:collection/:slug(.:format)                        wines#wine_detail
      style_detail GET      /wine/:style(.:format)                                   wines#style_detail

                   GET|POST /*path(.:format)                                         pages#error404

I also see an expected response in the console:

2.3.1 :003 > app.style_detail_path('semi-dry')
 => "/wine/semi-dry"

Yet, when I try to visit /wine/semi-sweet/ (Semi-sweet is a style "slug" which I use to search in the action) I get a 404 error.

What could I me missing? I've searched dozens of similar questions on S.O. and none of the solutions apply to my situation.

like image 495
emersonthis Avatar asked Nov 01 '25 06:11

emersonthis


1 Answers

It seems you need to specify constraints. When you say 'wines/semi-sweet', how would the router decide whether it's a style_detail path or a colletion_detail path? They both have the same mask '/wines/:something'

It should be something like:

scope 'wine' do
    get '/',                  to: 'wines#index',              as: 'wine_index'
    get '/:style',            to: 'wines#style_detail',       as: 'style_detail', constraints: proc { |r| Style.include?(r.params[:style]) }
    get '/:collection',       to: 'wines#collection_detail',  as: 'collection_detail'
    get '/:collection/:slug', to: 'wines#wine_detail',        as: 'wine_detail'
  end

This way the router will match predefined words (could be an array too) with wine styles, all the other strings will be considered as wine collections.

But it would be best to change the mask for these two paths, just to be safe, for example:

   get '/:style',            to: 'wines#style_detail',       as: 'style_detail'
   get '/c/:collection',       to: 'wines#collection_detail',  as: 'collection_detail'
like image 124
Dmitry Kukhlevsky Avatar answered Nov 03 '25 21:11

Dmitry Kukhlevsky



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!