【问题标题】:Ruby on Rails: :include on a polymorphic association with submodelsRuby on Rails: :include 与子模型的多态关联
【发布时间】:2011-01-24 07:18:15
【问题描述】:

使用多态关联时,是否可以在仅存在于某些类型中的子模型上运行包含?

例子:

class Container
  belongs_to :contents, :polymorphic => true
end
class Food
  has_one :container
  belongs_to :expiration
end
class Things
  has_one :container
end

在视图中,我想做一些类似的事情:

<% c = Containers.all %>
<% if c.class == Food %>
  <%= food.expiration %>
<% end %>

因此,我想在加载 c 时急切加载到期时间,因为我知道我将需要它们中的每一个。有什么办法吗?仅仅定义一个常规的 :include 就会出错,因为并非所有封闭的类型都有子模型到期。

【问题讨论】:

    标签: ruby-on-rails include polymorphic-associations eager-loading rails-activerecord


    【解决方案1】:

    已编辑答案

    我最近发现,当您按多态类型列进行过滤时,Rails 支持预先加载多态关联。所以没有必要声明虚假的关联。

    class Container
      belongs_to :content, :polymorphic => true
    end
    

    现在通过container_type查询Container

    containers_with_food = Container.find_all_by_content_type("Food", 
                               :include => :content)
    
    containers_with_thing = Container.find_all_by_content_type("Thing", 
                               :include => :content)
    

    旧答案

    这是一种 hack,因为没有直接的方法将多态对象包含在一个查询中。

    class Container
      belongs_to :contents, :polymorphic => true
      # add dummy associations for all the contents.
      # this association should not be used directly
      belongs_to :food
      belongs_to :thing
    end
    

    现在通过container_type查询Container

    containers_with_food = Container.find_all_by_content_type("Food", 
                               :include => :food)
    
    containers_with_thing = Container.find_all_by_content_type("Thing", 
                               :include => :thing)
    

    这导致对数据库的两次 SQL 调用(实际上是 4 次调用,因为 rails 为每个 :include 执行一个 SQL)

    没有办法在一个 SQL 中执行此操作,因为您需要为不同的内容类型设置不同的列。

    警告:不应直接使用 Content 类上的虚拟关联,因为它会导致意外结果。

    例如:假设contents 表中的第一个对象包含食物。

    Content.first.food # will work
    Content.first.thing
    

    第二次调用将不起作用。它可能会给你一个 Thing 对象,其 id 与 Content 指向的 Food 对象相同。

    【讨论】:

    • 我根据一些新信息更新了我的答案,看看吧。
    • 在 ActiveRecord 的哪个版本中,多态关联的预加载有效?在 3.2.3 中它不适用于我
    • @nicholaides 它应该在 3.2.3 中工作。只有当您按多态类型列进行过滤时,才会发生预加载。你遇到了什么错误?
    • "只有当您按多态类型列过滤时才会发生预加载"。啊,那部分我没看懂。我冒昧地更新了您的答案。希望你不要介意!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多