多使用多belongs_to的关联
问题描述:
我有两个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子句中的重复条件。这将返回主要成员姓氏如“弗洛伊德”的协议,但会忽略次要成员条件,因为别名不通过合并。
任何想法?
答
努力理解这一点之后,我结束了一个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的sifter
和scope
被更换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%')))
甜啊... 重启庆典。 ..现在我得到的协议有一个主要或次要成员,根据单个筛选器中定义的规则进行匹配。
对于他在斯奎尔所做的所有工作,一个大喊大叫的是厄尼米勒。