【问题标题】:Rails 3: Find parent of polymorphic model in controller?Rails 3:在控制器中查找多态模型的父级?
【发布时间】:2011-09-06 21:18:35
【问题描述】:

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

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)。

【问题讨论】:

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


    【解决方案1】:

    我不确定你到底想做什么,但如果你想找到“拥有”图片的对象,你应该能够使用 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
    

    这将为您实例化所有“imagables”。

    更新二:保利之怒 对于您的新方法,您可以将 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”。

    【讨论】:

    • 如果你真的想找,就做@picture.imagable_type.find(value)
    • @dogenpunk 如果图片必须与其他模型之一关联,Picture.allPicture.includes(:imageable).all 有什么区别?
    • includes(:imageable) 急切加载 imagable 关联引用的对象。
    • 除非您的用户实际上是通过此操作更新父类,否则我认为不需要实例化父类。您只是添加了一个不必要的数据库调用,因为您从请求对象中获得了所需的数据来实例化一个新的@picture。
    • 几乎是一样的……现在我们从 url 中提取名称,而不是从传递的参数中提取名称。我希望有一个params[:parent_model] 字段,因为无论如何你都是从父母那里来的。附言我在链接中搞砸了(employee**s**/:id/);将您的代码修改为 ...include p.pluralize } 。谢谢您的帮助。我想我会在 rails google group 发布这个。
    【解决方案2】:

    我也遇到了同样的问题。

    我解决它的方法是在每个具有多态关联的模型中定义一个 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
    

    很遗憾,我想不出更好的方法。希望这对您有所帮助。

    【讨论】:

      【解决方案3】:

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

      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 %>
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        相关资源
        最近更新 更多