用于显示操作的URL中的自定义参数

Jon*_*sen 10 ruby seo routing ruby-on-rails ruby-on-rails-3

我正在努力实现SEO-hiarchy,这意味着我需要为show动作添加参数.

用例是一个搜索站点,其URL结构为:
/cars/(:brand)/=>列表页面
/cars/(:brand)/(:model_name)?s=query_params=>搜索操作
/cars/:brand/:model_name/:variant/:id=>车展动作

我的问题是使show动作URL无需提供 :brand,:model_name :variant 作为单独的参数.它们始终可以作为资源上的值使用.

是)我有的: /cars/19330-Audi-A4-3.0-TDI

我想要的是 /cars/Audi/A4/3.0-TDI/19330

以前,这是routes.rb看起来像:

# Before
resources :cars. only: [:show] do
  member do
  get 'favourize'
  get 'unfavourize'
end
Run Code Online (Sandbox Code Playgroud)

以下是我的第一次尝试:

# 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
Run Code Online (Sandbox Code Playgroud)

这使得它成为可能:
cars_path(car, brand: 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
Run Code Online (Sandbox Code Playgroud)

路线工作正常,例如/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", :action=>"show", :locale=>"da", :brand=>"Audi", :model_name=>#<Car id: 487143, (...)>})
Run Code Online (Sandbox Code Playgroud)

Rails似乎不知道如何将to_param转换为有效链接.

Tom*_*son 1

好的,这就是我所得到的。这在我的小测试用例中有效。显然需要一些修复,我确信可以更加简洁和优雅,但我的座右铭是:“让它工作,让它漂亮,让它快速”:-)

routes.rb

  controller :cars do
    match 'cars', :to => "cars#index"
    match 'cars/:brand', :to => "cars#list_brand", :as => :brand
    match 'cars/:brand/:model', :to => "cars#list_model_name", :as => :model_name
    match 'cars/:brand/:model/:variant', :to => "cars#list_variant", :as => :variant
  end
Run Code Online (Sandbox Code Playgroud)

在汽车模型中

  def to_param
    "#{brand}/#{model_name}/#{variant}"
  end
Run Code Online (Sandbox Code Playgroud)

显然脆弱且不干燥,在cars_controller.rb

  def index
    @cars = Car.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @cars }
    end
  end

  def list_brand
    @cars = Car.where("brand = ?", params[:brand])

    respond_to do |format|
      format.html { render :index }
    end
  end

  def list_model_name
    @cars = Car.where("brand = ? and model_name = ?", params[:brand], params[:model])

    respond_to do |format|
      format.html { render :index }
    end
  end

  def list_variant
    @cars = Car.where("brand = ? and model_name = ? and variant = ?", params[:brand], params[:model], params[:variant])

    respond_to do |format|
      format.html { render :index }
    end
  end
Run Code Online (Sandbox Code Playgroud)