Rails 3:在控制器中找到多态模型的父级?

时间:2011-09-06 21:18:36

标签: ruby-on-rails-3 polymorphic-associations

我正在尝试找到一种优雅(标准)的方法来将多态模型的父级传递给视图。例如:

class Picture < ActiveRecord::Base
  belongs_to :imageable, :polymorphic => true
end

class Employee < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end 

class Product < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end

以下方式(find_imageable)有效,但似乎是“hackish”。

#PictureController(已更新,包括完整列表)

class PictureController < ApplicationController
  #/employees/:id/picture/new
  #/products/:id/picture/new
  def new
    @picture = imageable.pictures.new
    respond_with [imageable, @picture]
  end

  private
  def imageable
    @imageable ||= find_imageable
  end

  def find_imageable 
    params.each do |name, value|
      if name =~ /(.+)_id$/  
        return $1.classify.constantize.find(value)  
      end  
    end  
    nil
  end
end

有更好的方法吗?

修改

我正在做new行动。路径采用parent_model/:id/picture/new的形式,并且参数包括父ID(employee_idproduct_id)。

3 个答案:

答案 0 :(得分:6)

我不确定你要做什么,但如果你想找到'拥有'图片的对象,你应该可以使用imageable_type字段来获取类名。你甚至不需要辅助方法,只需

def show
  @picture = Picture.find(params[:id])
  @parent = @picture.imagable
  #=> so on and so forth
end

<强>更新 对于您可以执行的索引操作

def index
  @pictures = Picture.includes(:imagable).all
end

这将为你实现所有“想象力”。

更新II:Poly of Wrath 对于您的新方法,您可以将id传递给构造函数,但是如果要实例化父级,则可以从URL中获取它,如

def parent
  @parent ||= %w(employee product).find {|p| request.path.split('/').include? p }
end

def parent_class
  parent.classify.constantize
end

def imageable
  @imageable ||= parent_class.find(params["#{parent}_id"])
end

您当然可以在控制器中定义一个包含可能父项的常量,并使用它而不是明确地将它们列在方法中。使用请求路径对象对我来说感觉更多'Rails-y'。

答案 1 :(得分:1)

我遇到了同样的问题。

我解决这个问题的方法是在每个模型中定义一个具有多态关联的find_parent方法。

class Polymorphic1 < ActiveRecord::Base
  belongs_to :parent1, :polymorphic => true
  def find_parent
    self.parent1
  end
end

class Polymorphic2 < ActiveRecord::Base
  belongs_to :parent2, :polymorphic => true
  def find_parent
    self.parent2
  end
end

不幸的是,我想不出更好的方法。希望这对你有所帮助。

答案 2 :(得分:0)

这是我为多个嵌套资源执行此操作的方式,其中最后一个参数是我们正在处理的多态模型:(仅与您自己的略有不同)

def find_noteable
  @possibilities = []
  params.each do |name, value|
    if name =~ /(.+)_id$/  
      @possibilities.push $1.classify.constantize.find(value)
    end
  end
  return @possibilities.last
end

然后在视图中,这样的事情:

<% # Don't think this was needed: @possibilities << picture %>
<%= link_to polymorphic_path(@possibilities.map {|p| p}) do %>

返回该数组的最后一个的原因是允许查找有问题的子/ poly记录,即@ employee.pictures或@ product.pictures