Ruby on Rails ::包含与子模型的多态关联 [英] Ruby on Rails: :include on a polymorphic association with submodels

查看:174
本文介绍了Ruby on Rails ::包含与子模型的多态关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When working with a polymorphic association, is it possible to run an include on submodels that are only present in some types?

示例:

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

因此,我想在加载c时急切加载到期,因为我知道我将需要最后一个。有没有办法这样做?只是定义一个常规:include得到我的错误,因为并非所有封闭类型都有子模型到期。

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. Is there any way to do so? Just defining a regular :include gets me errors because not all enclosed types have a submodel expiration.

推荐答案

编辑的答案

我最近发现当你按多态类型列过滤时,Rails支持急切加载多态关联。所以没有必要声明假联想。

I recently found out that Rails supports eager loading of polymorphic associations when you filter by the polymorphic type column. So there is no need to declare fake associations.

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

现在查询 Container by container_type

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因为没有直接的方法在一个查询中包含多态对象。

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

现在通过 container_type 查询容器

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为每个执行一个SQL:include

That results in two SQL calls to the database ( actually it is 4 calls as rails executes one SQL for every :include)

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

There is no way to do this in one SQL as you need different column set for different content types.

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

Caveat: The dummy associations on Content class should not be used directly as it will result in unexpected results.

例如:让我们说第一个对象在th e 内容表包含食物。

E.g: Lets say the first object in the contents table contains food.

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

第二次通话无效。它可能会给你一个 Thing 对象,其id与内容指向的 Food 对象相同

The second call will not work. It might give you a Thing object with the same id as the Food object pointed by Content.

这篇关于Ruby on Rails ::包含与子模型的多态关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆