2012-06-07 181 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)

注意,我不是這個標記作爲解決方案,因爲這是一個變通,和無關的活動記錄。