2012-06-07 183 views
1

我一直有问题的Rails 3活动记录查询接口。我有一个查找表(查找),一个主表(through_references)和一个通过/连接表称为through_tables。因此,这是我使用has_many:through设置的HABTM配置。Rails 3的问题活动记录查询接口加入ID

更新:在此特别注意的是,当我正在进行这些连接时,我一直在加入ID以提供对记录的过滤。看来这不适用于Active Record Query Interface。如果你不想看到我的辛劳的血淋淋的细节,你可以跳到下面看到我的解决方法。

我们也将有一些主要项目(through_references表)应该能够有查找项目的任何组合,并且方便地能够通过复选框点击相关的查找项目。

我已在github上发布了验证码。关于github源代码有更多的解释。要查看结果,请转到查找索引页面。请注意,您将需要使用脚手架代码创建记录。

我也有代码运行在heroku,有更多的解释和例子。

class Lookup < ActiveRecord::Base 
    has_many :fk_references 
    has_many :through_tables 
    has_many :through_references, :through => :through_tables 
    attr_accessible :name, :value 
end 

class ThroughTable < ActiveRecord::Base 
    belongs_to :through_reference 
    belongs_to :lookup 
    attr_accessible :description, :through_reference_id, :lookup_id 
end 

class ThroughReference < ActiveRecord::Base 
    has_many :through_tables 
    has_many :lookups, :through => :through_tables 
    attr_accessible :description 
end 

如果我们想拥有的列表,如果所有的查询项目,并与他们对应的主要项目,我们可以LEFT JOIN的“查找”表的主要项目(through_references)表。 对应的SQL:

SELECT * FROM lookups 
    LEFT OUTER JOIN through_tables ON (lookups.id = through_tables.lookup_id AND through_tables.through_reference_id = 1) 
    LEFT OUTER JOIN through_references ON through_references.id = through_tables.through_reference_id 
    ORDER BY lookups.id 

返回的记录:

1;“Lookup Item 1”;“1”;“2012-06-06 17:14:40.819791”;“2012-06-06 17:14:40.819791”;1;1;1;“Main Item 1 has Lookup item 1”;“2012-06-06 17:17:31.355425”;“2012-06-06 17:17:31.355425”;1;“Main Item 1”;“2012-06-06 17:16:30.004375”;“2012-06-06 17:16:30.004375” 

2;“Lookup Item 2”;“2”;“2012-06-06 17:14:59.584756”;“2012-06-06 17:14:59.584756”;;;;“”;“”;“”;;“”;“”;“” 

3;“Lookup Item 3”;“3”;“2012-06-06 17:15:14.700239”;“2012-06-06 17:15:14.700239”;2;1;3;“Main Item 1 has Lookup item 3”;“2012-06-06 17:17:53.169715”;“2012-06-06 17:17:53.169715”;1;“Main Item 1”;“2012-06-06 17:16:30.004375”;“2012-06-06 17:16:30.004375” 

这是我所期待的。

===活动记录查询界面使用自定义左加入

Lookup.joins(“LEFT OUTER JOIN through_tables ON (lookups.id = through_tables.lookup_id AND through_tables.through_reference_id = 1)”).includes(:through_references).order(‘lookups.id’) 

从活动记录查询界面返回什么(请注意我浏览下来,通过活动记录层次):

Lookup ID Lookup Name Lookup Value Through Table ID Through Table Description Main Item ID Main Item Description 
1 Lookup Item 1 1 1 Main Item 1 has Lookup item 1 1 Main Item 1 
1 Lookup Item 1 1 3 Main Item 2 has Lookup item 1 2 Main Item 2 
2 Lookup Item 2 2 4 Main Item 2 has Lookup item 2 2 Main Item 2 
3 Lookup Item 3 3 2 Main Item 1 has Lookup item 3 1 Main Item 1 

这不是我所期望的。

我们这里有什么和简单的左连接(没有AND子句)相同。这告诉我在活动记录查询接口中AND子句被忽略。

使用===活动记录查询界面的find_by_sql方法

Lookup.find_by_sql("SELECT * FROM lookups LEFT OUTER JOIN through_tables ON (through_tables.lookup_id = lookups.id AND through_tables.through_reference_id = 1) LEFT OUTER JOIN through_references ON through_references.id = through_tables.through_reference_id ORDER BY lookups.value, through_references.id") 

什么是从活动记录查询界面返回(注意我浏览下来通过Active Record的层次)::

Lookup ID Lookup Name  Lookup Value Through Table ID Through Table Description Main Item ID Main Item Description 
1 Lookup Item 1 1 3 Main Item 2 has Lookup item 1 2 Main Item 2 
1 Lookup Item 1 1 1 Main Item 1 has Lookup item 1 1 Main Item 1 
    Lookup Item 2 2 No through_tables entry 
1 Lookup Item 3 3 3 Main Item 2 has Lookup item 1 2 Main Item 2 
1 Lookup Item 3 3 1 Main Item 1 has Lookup item 1 1 Main Item 1 

的这里的结果很疯狂!

这是一个错误,这是预期的效果,还是我错过了什么?

我希望有一个干净的方式来做到这一点,而不必生成两个结果集,并通过代码合并它们。

回答

0

好了,看完GitHub的项目,我看到:

我真正想要做的是所有的查询项目, 如果有匹配的主要项目,让他们附加的列表回到 返回的记录,如果没有,我想空值。这是我使用了10年以上的技术。

我在想,这个问题正是你想要这样做的时候,让rails更加自然地加载它来处理它,所以你已经注意到一切都在一个单一的大规模加入。

我会做的是一样的东西:

Lookup.where(..在这里插入任何需要的条件...)的。(:through_tables)

然后ActiveQuery然后将取在一个查询中查找所有查找,然后使用预先加载来获取包含语句中指定的任何关联,每个关联有一个查询。

注意我并不是说连接不好,只是说这是一种更自然的方式来实现它。我喜欢使用预加载器http://apidock.com/rails/ActiveRecord/Associations/Preloader来区分决定哪些数据要提取的决定。我发现这对控制器很有帮助 - 让模型决定条件是什么,但让控制器决定需要加载哪些对象。

HTH

+0

我不是专注于在一个大规模连接中获取所有东西。如果你注意到github项目,我尝试了where子句,它没有返回所有的查找项目,也没有作为sql where子句。请查看heroku页面。我会投票给你,但我没有排名做到这一点。 –

+0

通过使用包含hash的内容(检查github或heroku上面),我对where子句有了一些理解。现在它的功能就像SQL where子句(这不能解决我的问题)。 –

1

我找到了解决办法。问题似乎是Active Record不会识别过滤ID的连接(LEFT OUTER JOIN xyz ON xyz.id = ID)。

我的解决方法涉及创建一个存储过程或函数,它将ID作为参数,在数据库中进行连接,并返回一个漂亮的平面记录集。

看到:Heroku demo page (skip to bottom)

注意,我不是这个标记作为解决方案,因为这是一个变通,和无关的活动记录。