路由别名,有可能吗?

时间:2010-06-07 08:38:11

标签: ruby-on-rails ruby

我有车型:

路线:

map.resources :vehicles, :has_many => :suppliers

一切都很好,但是Vehicle有一个布尔属性 is_truck 。我想做一个Alias所以我可以获得相同的资源只过滤卡车,我试过:

路线:

map.trucks '/trucks', :controller => :vehicles, :action => :index, :is_truck => true
map.trucks '/trucks/by_supplier/:supplier', :controller => :vehicles, :action => :index, :is_truck => true

第一个效果很好,但是当我在表单中搜索时,第二个不起作用并搜索所有供应商。

控制器:

class VehiclesController
   def index
     if params[:supplier]
       @vehicles = Vehicle.all :conditions => { :is_truck => params[:is_truck] }
     else
       @vehicles = Vehicle.all
     end
   end
   ...
end

搜索表单

<% form_for :truck, :url => {:controller => :trucks, :action => :index}, :html => {:method => :get} do |f| %>
  <% f.text_field :search %>
  <% f.submit 'Search Trucks' %>
<% end %>

是否可以 map.resources 作为别名?

5 个答案:

答案 0 :(得分:1)

我找到了一种更干净的方法,但在某个特定供应商下搜索仍然无法

# Show all vehicles
map.connect '/vehicles/supplier/:supplier', :controller => :vehicles, :action => :index
map.resources :vehicles

# Only show trucks
map.connect '/trucks/supplier/:supplier', :controller => :vehicles, :action => :index, :is_truck => true
map.resources :vehicles, :as => 'trucks', :requirements => { :is_truck => true }

资源:http://api.rubyonrails.org/classes/ActionController/Resources.html

答案 1 :(得分:1)

只需按以下方式修改路线:

map.resources :vehicles, :has_many => :suppliers,
                         :collection => { :trucks => :get }

并检查rake routes生成的路线。它将允许您列出卡车的车辆:

trucks_vehicles GET /vehicles/trucks(.:format)
                    {:controller=>"vehicles", :action=>"trucks"}

所以你现在只需要添加一个名为“truck”的新动作,其作用类似于“index”。如果您创建卡车或其他车辆,表格应该自己跟踪(通过表单字段)。不要尝试使用rails路由,这通常意味着您的应用程序设计存在缺陷,这会让您以后遇到麻烦。

您可以查看STI(单表继承:一个表存储多个类别的车辆)。另一种方法是创建一个卡车控制器,它继承了车辆控制器并覆盖了一些类似的方法:

class TrucksController < VehiclesController
  def new
    @is_truck = true
    super
  end
  ...
end

class TrucksController < VehiclesController
  before_filter :this_is_a_truck
  ...

  private

  def this_is_a_truck
    @is_truck = true
    super
  end
end

更新:这是另一个(假设您有一个is_truck列):

class TrucksController < VehiclesController
  around_filter :with_truck_scope
  ...

  private

  # Scope every active record access with an is_truck condition
  # you may want to put this directly into the model to get rid of the .send
  # method and directly access "Vehicle.with_truck_scope &block" here
  def with_truck_scope(&block)
    Vehicle.send :with_scope, :find => { :conditions => "is_truck = 1" },
                              :create => { :is_truck => 1 }, &block
  end
end

但我建议首先尝试使用Rails路由的:collection:member参数。

答案 2 :(得分:0)

你在控制器中处理它吗?

像往常一样:

class VehiclesController
   def index
     if params[:supplier]
       @vehicles = Vehicle.all :conditions => { :supplier_id => params[:supplier] }
     else
       @vehicles = Vehicle.all
     end
   end
end

答案 3 :(得分:0)

不确定是否可以制作别名,但至少可以尝试交换路线:

map.trucks '/trucks/by_supplier/:supplier', :controller => :vehicles, :action => :index, :is_truck => true
map.trucks '/trucks', :controller => :vehicles, :action => :index, :is_truck => true

由于路线的工作方式类似于“首次添加 - 具有更高的优先级”,因此您的解决方案可能会失败,因为map.trucks'/ truck'也会捕获'/ trucks / by_supplier /:supplier'。我也建议稍微重构一下:

map.with_options :controller => :vehicles, :action => :index, :is_truck => true do |v|
  v.trucks '/trucks/by_supplier/:supplier'
  v.trucks '/trucks'
end

答案 4 :(得分:0)

我建议您使用其他资源,只需添加:

map.resources :vehicles, :as => :trucks, :has_many => :suppliers

然后在控制器中处理它,例如:

def index 
  conds = {}
  conds = { ... } if request.uri =~ /trucks/ # you can be more specific about the regexp if you need to
  @vehicles = Vehicle.all :conditions => conds      
end

你怎么看?