Rails路由出现在路由中但抛出404

时间:2017-01-26 19:35:13

标签: ruby-on-rails ruby routing ruby-on-rails-5

我试图向现有的控制器/操作添加一条简单的路线,但奇怪的是,即使路线似乎存在,我也会收到404错误。

这是我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

这似乎是正确的,因为这是我在查看时看到的内容:

$ 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

我还在控制台中看到了预期的响应:

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

然而,当我尝试访问/wine/semi-sweet/时(半甜是一种风格" slug"我用它来搜索动作)我收到404错误。

我能错过什么?我在S.O.上搜索过几十个类似的问题。并且没有一个解决方案适用于我的情况。

1 个答案:

答案 0 :(得分:2)

似乎您需要指定约束。当你说'wines / semi-sweet'时,路由器将如何判断它是style_detail路径还是colletion_detail路径?他们都有相同的面具'/ wines /:something'

应该是这样的:

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

这样路由器将匹配预定义的单词(也可能是一个数组)和葡萄酒样式,所有其他字符串将被视为葡萄酒收藏。

但最好更改这两条路径的掩码,只是为了安全,例如:

   get '/:style',            to: 'wines#style_detail',       as: 'style_detail'
   get '/c/:collection',       to: 'wines#collection_detail',  as: 'collection_detail'