我有两个查询,我需要一个 or
,即我想要的结果是第一个查询或第二个查询。
第一个查询是一个简单的where()
,可获取所有可用的项目。
@items = @items.where(available: true)
第二个包括一个join()
并提供当前用户的项目。
@items =
@items
.joins(:orders)
.where(orders: { user_id: current_user.id})
我试图以各种形式将它们与Rails的or()
方法相结合,包括:
@items =
@items
.joins(:orders)
.where(orders: { user_id: current_user.id})
.or(
@items
.joins(:orders)
.where(available: true)
)
但是我一直遇到此错误,我不确定如何修复它。
Relation passed to #or must be structurally compatible. Incompatible values: [:references]
在github上有一个已知问题。
根据此评论,您可能需要覆盖structurally_incompatible_values_for_or
以克服问题:
def structurally_incompatible_values_for_or(other)
Relation::SINGLE_VALUE_METHODS.reject { |m| send("#{m}_value") == other.send("#{m}_value") } +
(Relation::MULTI_VALUE_METHODS - [:eager_load, :references, :extending]).reject { |m| send("#{m}_values") == other.send("#{m}_values") } +
(Relation::CLAUSE_METHODS - [:having, :where]).reject { |m| send("#{m}_clause") == other.send("#{m}_clause") }
end
也总是有一个使用SQL的选项:
@items
.joins(:orders)
.where("orders.user_id = ? OR items.available = true", current_user.id)
您可以以这种良好的旧方式编写查询,以避免错误
@items = @items.joins(:orders).where("items.available = ? OR orders.user_id = ?", true, current_user.id)
希望有帮助!
hacky解决方案:在.or
之后执行所有.joins
。这将Checker隐藏了有问题的.joins
。也就是说,将原始问题中的代码转换为...
@items =
@items
.where(orders: { user_id: current_user.id})
.or(
@items
.where(available: true)
)
.joins(:orders) # sneaky, but works! 😈
更一般地,以下两行将失败
A.joins(:b).where(bs: b_query).or(A.where(query)) # error! 😞
A.where(query).or(A.joins(:b).where(bs: b_query)) # error! 😞
但重新排列如下,您可以逃避检查器:
A.where(query).or(A.where(bs: b_query)).joins(:b) # works 😈
这起作用,因为所有检查都发生在.or()
方法内。在下游结果上,这是幸福的Shennanigans。
一个缺点当然不是很好。
我遇到了同一问题,但是代码是在另一个地方定义的,很难直接更改。
# I can't change "p"
p = Post.where('1 = 1').distinct # this could also be a join
我需要向其添加or
语句
p.or(Post.where('2 = 2'))
以下代码不会引起错误,因为它具有distinct
,例如初始关系。
p.or(Post.where('2 = 2').distinct)
只要您知道这种关系,它的问题就可以工作。它可能具有或没有join
或distinct
。
这项工作不管是什么关系:
p.or(p.unscope(:where).where('2 = 2'))
=> SELECT DISTINCT `posts`.* FROM `posts` WHERE ((1 = 1) OR (2 = 2))
当您尝试结合同一类型的两个多活动记录时,会发生这种情况,但是其中一个具有加入值或一个值,或者包括值,或者在您的情况下为参考值,另一个没有。因此,我们需要匹配它们之间的值,我找到了一种一般的方法来执行此操作,而又不知道实际值。
items_1 = @items.joins(:orders)
.where(orders: { user_id: current_user.id})
items_2 = @items.where(available: true)
.joins(items_1.joins_values)
.includes(items_1.includes_values)
.references(items_1.references_values)
@items = items_1.or(items_2)
只是解决它!
def exec_or_statement(q1, q2)
klass = q1.klass
key = klass.primary_key
query_wrapper_1 = {}
query_wrapper_1[key] = q1
query_wrapper_2 = {}
query_wrapper_2[key] = q2
klass.where(query_wrapper_1).or(klass.where(query_wrapper_2))
end
query_1 = @items.where(available: true)
query_2 =
@items
.joins(:orders)
.where(orders: { user_id: current_user.id})
exec_or_statement(query_1, query_2)