用例是URL结构的搜索网站:
/ cars /(:brand)/ =>列表页面
/ cars /(:brand)/(:model_name)?s = query_params =>搜索动作
/ cars /:brand /:model_name /:variant /:id =>一个车展动作
我的问题是使show action URL工作,而无需提供:brand,:model_name和:variant作为单独的参数.它们总是作为资源上的值提供.
我拥有的:
/cars/19330-Audi-A4-3.0-TDI
我想要的是
/cars/Audi/A4/3.0-TDI/19330
以前,这是route.rb的样子:
# Before resources :cars. only: [:show] do member do get 'favourize' get 'unfavourize' end
以下是我的第一次尝试:
# First attempt scope '/cars/:brand/:model_name/:variant' do match ":id" => 'cars_controller#show' match ":car_id/favourize" => 'cars_controller#favourize',as: :favourize_car match ":car_id/unfavourize" => 'cars_controller#unfavourize',as: :unfavourize_car end
这样做可以做到:
cars_path(汽车,品牌:car.brand,model_name:car.model_name,variant:car.variant)
但这显然不是很理想.
如何设置路由(也可能是.to_param方法?)的方式是不会变得所有link_to调用的一个繁琐的工作?
提前致谢!
– 更新 –
对于@ tharrisson的建议,这是我试过的:
# routes.rb match '/:brand/:model_name/:variant/:id' => 'cars#show',as: :car #car.rb def to_param # Replace all non-alphanumeric chars with -,then merge adjacent dashes into one "#{brand}/#{model_name}/#{variant.downcase.gsub(/[^[:alnum:]]/,'-').gsub(/-{2,}/,'-')}/#{id}" end
路线工作正常,例如/cars/Audi/A4/3.0-TDI/19930显示正确的页面.然而,生成与to_param的链接不起作用.例:
link_to "car link",car_path(@car) #=> ActionView::Template::Error (No route matches {:controller=>"cars",:action=>"show",:locale=>"da",:brand=>#<Car id: 487143,(...)>}) link_to "car link 2",car_path(@car,brand: "Audi") #=> ActionView::Template::Error (No route matches {:controller=>"cars",:brand=>"Audi",:model_name=>#<Car id: 487143,(...)>})
Rails似乎不知道如何将to_param转换为有效的链接.
解决方法
第一次尝试时,您的网址识别工作,但不是一代.我可以看到,使代码工作的解决方案是覆盖car_path辅助方法.
另一个解决方案可能就像你在UPDATE中一样来覆盖Car的to_param方法.请注意,您的问题不在to_param方法中,而是在路由定义中:您需要在要生成路由时给出:brand,:model_name和:variant参数.为了处理这个问题,你可能想在你的路线上使用一个Wildcard segment.
最后还可以使用routing-filter gem,这样可以在url识别/生成之前和之后添加逻辑.
对我来说,看起来所有的这些解决方案都有点沉重,而不是那么容易,但我相信这是来自你的需要,因为你想在URL中添加一些级别,而不必严格遵循将给你的URL的行为喜欢/品牌/ audi /型号/ A3 / variant / 19930