简体   繁体   English

Ruby on Rails ::包含与子模型的多态关联

[英]Ruby on Rails: :include on a polymorphic association with submodels

When working with a polymorphic association, is it possible to run an include on submodels that are only present in some types? 使用多态关联时,是否可以在仅存在于某些类型中的子模型上运行包含?

Example: 例:

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

In the view I'm going to want to do something like: 在视图中我想要做的事情如下:

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

Therefore, I'd like to eager load the expirations when I load up c, because I know I will need every last one of them. 因此,当我加载c时,我想急切加载到期,因为我知道我将需要最后一个。 Is there any way to do so? 有没有办法这样做? Just defining a regular :include gets me errors because not all enclosed types have a submodel expiration. 只定义一个常规:include得到我的错误,因为并非所有封闭类型都有子模型到期。

Edited Answer 编辑答案

I recently found out that Rails supports eager loading of polymorphic associations when you filter by the polymorphic type column. 我最近发现当你按多态类型列过滤时,Rails支持急切加载多态关联。 So there is no need to declare fake associations. 所以没有必要声明假联想。

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

Now query the Container by container_type . 现在通过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)

Old Answer 老答案

This is a hack as there is no direct way to include the polymorphic objects in one query. 这是一个黑客,因为没有直接的方法在一个查询中包含多态对象。

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

Now query the Container by container_type . 现在通过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)

That results in two SQL calls to the database ( actually it is 4 calls as rails executes one SQL for every :include ) 这导致对数据库的两次SQL调用(实际上是4个调用,因为rails为每个执行一个SQL :include

There is no way to do this in one SQL as you need different column set for different content types. 在一个SQL中无法执行此操作,因为您需要为不同的内容类型设置不同的列。

Caveat: The dummy associations on Content class should not be used directly as it will result in unexpected results. 警告:不应直接使用Content类上的虚拟关联,因为它会导致意外结果。

Eg: Lets say the first object in the contents table contains food. 例如:假设contents表中的第一个对象包含食物。

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

The second call will not work. 第二个电话不起作用。 It might give you a Thing object with the same id as the Food object pointed by Content . 它可能会为您提供一个与Content指向的Food对象具有相同ID的Thing对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM