Rails: OR where 关联条件
Rails: OR where condition on association
我有一个名为 Facility
的模型。它has_many :addresses
。 Address
模型 has_one :city
。
现在我要运行一个条件:
- 获取所有没有关联地址的设施;
- 如果他们有地址,请检查他们是否没有与该地址关联的城市模型。
我已经尝试了第一个条件,但我无法为其组合 OR。
这会获取所有没有关联地址模型的设施
Facility.includes(:addresses).where( :addresses => {:facility_id => nil})
一些错误尝试是:
Facility.includes(:addresses).where( :addresses => ({:facility_id => nil}).or({:city_id => nil}) );
Facility.includes(:addresses).where( :addresses => ({:facility_id => nil}).or(:address => {:city_id => nil}) )
试试这个
Facility.includes(addresses: :city).where("addresses.facility_id IS NULL OR addresses.city_id IS NULL");
希望这会有所帮助。
尝试以下操作:
Facility.includes(:addresses)
.where('addresses.facility_id is null or addresses.city_id is null')
.references(:addresses)
您还可以找到有趣的 ,关于 activerecord 查询中 or
条件的可能实现。
首先,当您想对关联设置条件时使用 includes
可能会产生负面影响:
- 您会急于加载数据,如果不需要,这意味着白白做更多的工作
- 预加载的
addresses
只是匹配条件的。因此,如果您随后使用 addresses
,您不会获得该记录的所有记录(只有那些与条件匹配的记录)。这会导致奇怪的错误或难以理解的工作代码。
为了避免这个问题和所有其他问题,我建议使用我专门为此制作的 gem:activerecord_where_assoc
你的问题可以简化,我会在原样回复你的请求后这样做:
根据标签,您似乎在使用 Rails 4.2。所以您还没有访问#or 方法的权限。所以你可以这样做:
sql_no_address = Facility.assoc_not_exists_sql(:addresses)
sql_no_city = Facility.assoc_exists_sql(:addresses) { where_assoc_not_exists(:city) }
Facility.where("#{sql_no_address} OR #{sql_no_city}")
如果您有 Rails 5 个或更多:
Facility.where_assoc_not_exists(:addresses).or(Facility.where_assoc_not_exists([:addresses, :city]))
现在,一个更简单的解决方案。请注意,如果一个设施没有地址,那么它就不可能有一个城市,因为它必须通过一个地址才能到达一个城市。真的,你的问题只是“我想要没有城市的设施”。这就是将数组传递给方法所做的事情,它会尝试从一个到另一个直到结束。
Facility.where_assoc_not_exists([:addresses, :city])
这是introduction and examples. Read more details in the documentation.
我有一个名为 Facility
的模型。它has_many :addresses
。 Address
模型 has_one :city
。
现在我要运行一个条件:
- 获取所有没有关联地址的设施;
- 如果他们有地址,请检查他们是否没有与该地址关联的城市模型。
我已经尝试了第一个条件,但我无法为其组合 OR。
这会获取所有没有关联地址模型的设施
Facility.includes(:addresses).where( :addresses => {:facility_id => nil})
一些错误尝试是:
Facility.includes(:addresses).where( :addresses => ({:facility_id => nil}).or({:city_id => nil}) );
Facility.includes(:addresses).where( :addresses => ({:facility_id => nil}).or(:address => {:city_id => nil}) )
试试这个
Facility.includes(addresses: :city).where("addresses.facility_id IS NULL OR addresses.city_id IS NULL");
希望这会有所帮助。
尝试以下操作:
Facility.includes(:addresses)
.where('addresses.facility_id is null or addresses.city_id is null')
.references(:addresses)
您还可以找到有趣的 or
条件的可能实现。
首先,当您想对关联设置条件时使用 includes
可能会产生负面影响:
- 您会急于加载数据,如果不需要,这意味着白白做更多的工作
- 预加载的
addresses
只是匹配条件的。因此,如果您随后使用addresses
,您不会获得该记录的所有记录(只有那些与条件匹配的记录)。这会导致奇怪的错误或难以理解的工作代码。
为了避免这个问题和所有其他问题,我建议使用我专门为此制作的 gem:activerecord_where_assoc
你的问题可以简化,我会在原样回复你的请求后这样做:
根据标签,您似乎在使用 Rails 4.2。所以您还没有访问#or 方法的权限。所以你可以这样做:
sql_no_address = Facility.assoc_not_exists_sql(:addresses)
sql_no_city = Facility.assoc_exists_sql(:addresses) { where_assoc_not_exists(:city) }
Facility.where("#{sql_no_address} OR #{sql_no_city}")
如果您有 Rails 5 个或更多:
Facility.where_assoc_not_exists(:addresses).or(Facility.where_assoc_not_exists([:addresses, :city]))
现在,一个更简单的解决方案。请注意,如果一个设施没有地址,那么它就不可能有一个城市,因为它必须通过一个地址才能到达一个城市。真的,你的问题只是“我想要没有城市的设施”。这就是将数组传递给方法所做的事情,它会尝试从一个到另一个直到结束。
Facility.where_assoc_not_exists([:addresses, :city])
这是introduction and examples. Read more details in the documentation.