2013-03-07 28 views
0

我有兩個belongs_to的協會會員類的類協議連接到相同型號 - 引用爲原發性和繼發性:多使用多belongs_to的關聯

class Agreement < ActiveRecord::Base 
    belongs_to :primary, class_name: 'Member' 
    belongs_to :secondary, class_name: 'Member' 
    ... 

    def self.by_member(member_attribute_hash) 
    # returns any agreements that has a primary OR secondary member that matches any of the values 
    # in the member_attribute_hash 
    ... 
    end 
end 

會員類沒有關聯的知識該協議類 - 它並不需要:

class Member < ActiveRecord::Base 
    # contains surname, given_names, member_number 
    ... 

    def self.by_any(member_attribute_hash) 
    # returns any member where the member matches on surname OR given_names OR member_number 
    ... 
    end 
end 

我想要做的就是搜索,其中主要或次要構件的一套標準匹配的所有協議。

從以前的工作(see question #14139609),我已經整理了如何爲Member.by_any()構建條件where子句。

試圖重新使用方法,同時尋求協議使我試試這個:

class Agreement < ActiveRecord::Base 
    ... 

    def self.by_member(member_attribute_hash) 
    Agreement.joins{primary.outer}.merge(Member.by_any(member_attribute_hash)).joins{secondary.outer}.merge(Member.by_any(member_attribute_hash)) 
    end 
end 

在控制檯中運行此,有member_attribute_hash = {surname: 'Freud'},生成的SQL不履行的第二個連接產生的別名到會員:

SELECT "agreements".* 
FROM "agreements" 
    LEFT OUTER JOIN "members" 
     ON "members"."id" = "agreements"."primary_id" 
    LEFT OUTER JOIN "members" "secondarys_agreements" 
     ON "secondarys_agreements"."id" = "agreements"."secondary_id" 
WHERE "members"."surname" ILIKE 'Freud%' 
    AND "members"."surname" ILIKE 'Freud%' 

注意WHERE子句中的重複條件。這將返回主要成員姓氏如「弗洛伊德」的協議,但會忽略次要成員條件,因爲別名不通過合併。

任何想法?

回答

0

努力理解這一點之後,我結束了一個Squeel sifter更換Member.by_any範圍:

class Member < ActiveRecord::Base 
    # contains surname, given_names, member_number 
    ... 

    def self.by_any(member_attribute_hash) 
    # returns any member where the member matches on surname OR given_names OR member_number 
    squeel do 
     [ 
     (surname =~ "#{member[:surname]}%" if member[:surname].present?), 
     (given_names =~ "#{member[:given_names]}%" if member[:given_names].present?), 
     (member_number == member[:member_number] if member[:member_number].present?) 
     ].compact.reduce(:|) 
     # compact to remove the nils, reduce to combine the cases with | 
    end 
    end 
end 

唯一的區別(代碼明智),bewteen的sifterscope被更換where的在篩選器中的範圍爲squeel

所以,而是採用了merge訪問從協議模型Member.by_any範圍,現在我可以從協議參考模型的Member :by_any篩。它看起來像:

class Agreement < ActiveRecord::Base 
    ... 

    def self.by_member(member_attribute_hash) 
    Agreement.joins{primary.outer}.where{primary.sift :by_any, member_attribute_hash}.joins{secondary.outer}.where{secondary.sift :by_any, member_attribute_hash} 
    end 
end 

這固定了別名問題 - 開始慶祝!

SELECT "agreements".* 
FROM "agreements" 
    LEFT OUTER JOIN "members" 
     ON "members"."id" = "agreements"."primary_id" 
    LEFT OUTER JOIN "members" "secondarys_agreements" 
     ON "secondarys_agreements"."id" = "agreements"."secondary_id" 
WHERE "members"."surname" ILIKE 'Freud%' 
    AND "secondarys_agreements"."surname" ILIKE 'Freud%' 

但我還是沒有得到我希望的結果 - 慶祝擱置。什麼問題? Where子句中的AND錯誤。多一點挖(一夜遠離電腦)後,刷新頭腦決定試試這個:

class Agreement < ActiveRecord::Base 
    ... 

    def self.by_member(member_attribute_hash) 
    Agreement.joins{primary.outer}.joins{secondary.outer}.where{(primary.sift :by_any, member_attribute_hash) | (secondary.sift :by_any, member_attribute_hash)} 
    end 
end 

生產這樣的:

SELECT "agreements".* 
FROM "agreements" 
    LEFT OUTER JOIN "members" 
     ON "members"."id" = "agreements"."primary_id" 
    LEFT OUTER JOIN "members" "secondarys_agreements" 
     ON "secondarys_agreements"."id" = "agreements"."secondary_id" 
WHERE ((("members"."surname" ILIKE 'Freud%') 
    OR ("secondarys_agreements"."surname" ILIKE 'Freud%'))) 

甜啊... 重啓慶典。 ..現在我得到的協議有一個主要或次要成員,根據單個篩選器中定義的規則進行匹配。

對於他在斯奎爾所做的所有工作,一個大喊大叫的是厄尼米勒。