Rails - 简洁地找到多态嵌套资源的父资源

Sai*_*Sai 5 routing routes ruby-on-rails polymorphic-associations

假设我有这样的多态结构.

map.resources :bar, :has_many => :foo
map.resources :baz, :has_many => :foo
map.resources :qux, :has_many => :foo

class Foo
  belongs_to :parent, :polymorphic => true
end

class FooController < AC
 before_filter :find_parent

 ...

 private
 def find_parent
  # ugly way:
  @parent = if params[:bar_id]
   Bar.find(params[:bar_id])
  elsif params[:baz_id]
   Baz.find(params[:baz_id])
  elsif params[:qux_id]
   Qux.find(params[:qux_id])
  end 
 end
end
Run Code Online (Sandbox Code Playgroud)

那太难看了.每当我们添加一个它可能属于的新东西时,我们需要将它非干扰地添加到before_filter.

它也变得更糟.假设Foos 真的是可以在任何地方出现的多态事物,比如评论或标签.并假设您有以下路线:

map.resources :bar, :has_many => :foo do |bar|
 bar.resources :baz, :has_many => :foo
end
map.resources :qux, :has_many => :foo do |qux|
 qux.resources :baz, :has_many => :foo
end
Run Code Online (Sandbox Code Playgroud)

...现在我们要担心是先检查bar_id还是baz_id.

对于更复杂的资源,这可能甚至不足以确保您获得父级的ID.

如果我们可以做这样的事情,那将是理想的:

def get_parent
 # fetch the parameter that immediately preceeded :id
 @parent = if x = params.before(:id)
   # polymorphic find
   x.key.to_s[0..-4].classify.constantize.find x.value
 end
end
Run Code Online (Sandbox Code Playgroud)

毕竟,我们的路由已经根据URL中的参数顺序对父进行编码.为何放弃这些信息?

那么:怎么做呢?

Mar*_*rom 4

您应该能够请求 foo.parent

你需要有这样的东西:

class Bar < ActiveRecord::Base
  has_many :foos, :as => :parent
  ...
end
Run Code Online (Sandbox Code Playgroud)