传递给#or 的关系必须在结构上兼容。不兼容的值:[:references]
Relation passed to #or must be structurally compatible. Incompatible values: [:references]
我有两个查询,它们之间需要一个 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]
有个known issue about it on Github.
根据this comment you might want to override the 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
。这对检查器隐藏了违规的 .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()
方法中。它很幸运地没有意识到下游结果的恶作剧。
一个缺点当然是它读起来不太好。
我有两个查询,它们之间需要一个 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]
有个known issue about it on Github.
根据this comment you might want to override the 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
。这对检查器隐藏了违规的 .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()
方法中。它很幸运地没有意识到下游结果的恶作剧。
一个缺点当然是它读起来不太好。