【问题标题】:How to eager load objects with a custom join in rails?如何在 Rails 中使用自定义连接预加载对象?
【发布时间】:2010-09-12 21:59:35
【问题描述】:

背景

正常的 rails 急切加载集合的工作方式如下:

Person.find(:all, :include=>:companies)

这会生成一些 sql

LEFT OUTER JOIN companies ON people.company_id = companies.id

问题

但是,我需要一个自定义连接(如果我使用 find_by_sql,也会出现这种情况)所以我不能使用原版 :include => :companies

自定义 join/sql 将为我提供所需的所有数据,但我如何告诉 activerecord 它属于关联的Company 对象,而不仅仅是一堆额外的行?

更新

我需要在连接中添加额外的条件。像这样的:

SELECT blah blah blah
LEFT OUTER JOIN companies ON people.company_id = companies.id AND people.magical_flag IS NULL 
<Several other joins>
WHERE blahblahblah

【问题讨论】:

  • 我遇到了同样的问题。开箱即用基本上不可能对 JOIN 而不是 WHERE 施加动态条件。插件/猴子补丁似乎是现阶段唯一合理的解决方案。
  • 你有没有参考任何插件/补丁来完成这个?

标签: sql ruby-on-rails ruby activerecord


【解决方案1】:

不能用 ActiveRecord 添加加入条件吗?

例如,我有一个非常复杂的查询,它使用了多个依赖记录,并且通过组合条件和包含指令可以正常工作

Contractors.find(
  :all, 
  :include => {:council_areas => :suburbs},
  :conditions => ["suburbs.postcode = ?", customer.postcode]                 
)    

假设:

  1. 承包商有_many CouncilAreas
  2. CouncilAreas has_many Suburbs

此联接返回由 customer.postcode 标识的郊区的承包商。

生成的查询如下所示:

SELECT contractors.*, council_areas.*, suburbs.*
FROM `contractors` 
LEFT OUTER JOIN `contractors_council_areas` ON `contractors_council_areas`.contractor_id = `contractors`.id 
LEFT OUTER JOIN `council_areas` ON `council_areas`.id = `contractors_council_areas`.council_area_id 
LEFT OUTER JOIN `council_areas_suburbs` ON `council_areas_suburbs`.council_area_id = `council_areas`.id 
LEFT OUTER JOIN `suburbs` ON `suburbs`.id = `council_areas_suburbs`.suburb_id WHERE (suburbs.postcode = '5000')

(注意:为简洁起见,我编辑了列列表)。

【讨论】:

    【解决方案2】:

    您可以使用类似以下的方法来获得适当的左外连接语法魔法。

    Person.reflect_on_association(:companies).options[:conditions] = 'people.magical_flag IS NULL'
    

    【讨论】:

      【解决方案3】:

      我不确定这是你想要的(我不是 100% 确定我已经理解了你的问题以及你想要完成的事情)但是:

      同时提供:joins:includes 怎么样?

      Person.find( :all, :joins => 'LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_', :includes => :companies )

      或AR3方式:

      Person.includes(:companies).joins('LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_')

      【讨论】:

        【解决方案4】:

        您能否详细说明您想通过此查询完成的具体内容?

        还可以查看 find 的 :joins 选项。它允许您指定要如何连接表。 link text

        使用 :include 时要小心,Rails 2.1 中的行为会发生一些变化,并且在与引用包含表的 :conditions 选项结合使用时可能会导致一些问题。 link textlink text 是 Pivotal 的两篇文章,其中提到了这个问题。

        【讨论】:

        • 我正在使用带有字符串的 :joins 选项,但这(据我所知)会破坏急切加载,因此我的问题是 :-)
        猜你喜欢
        • 1970-01-01
        • 2021-02-18
        • 1970-01-01
        • 1970-01-01
        • 2019-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多