传递给 #or 的关系必须在结构上兼容。不兼容的值:[:references]
Posted
技术标签:
【中文标题】传递给 #or 的关系必须在结构上兼容。不兼容的值:[:references]【英文标题】:Relation passed to #or must be structurally compatible. Incompatible values: [:references] 【发布时间】:2017-04-06 03:23:26 【问题描述】:我有两个查询,我需要它们之间的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]
【问题讨论】:
【参考方案1】:有一个known issue about it on Github。
根据this comment,您可能需要覆盖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)
【讨论】:
改为使用 SQL 查询。感谢您的信息。 @Andrey 应该参考我的答案,而不是编辑你的答案并添加相同的答案。无论如何,为第一个解决方案 +1。 @RSB 我打算从 sql 部分开始,而不是用谷歌搜索错误消息并发现 github 问题。毕竟我仍然决定添加我最初的想法,因为它的代码更少。【参考方案2】:您可以用这种古老的方式编写查询以避免错误
@items = @items.joins(:orders).where("items.available = ? OR orders.user_id = ?", true, current_user.id)
希望有帮助!
【讨论】:
【参考方案3】: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()
方法内。它对下游结果的恶作剧一无所知。
当然,一个缺点是它的阅读效果不太好。
【讨论】:
这为我解决了这个问题。这真的应该是答案。 已为我修复。谢谢 ! joins 和 includes 必须在 or 之后添加。有人可以解释为什么,如果这可行,rails 不接受我们在 'or' 之前添加它? @LiKaZ forjoins
,我认为没有什么好的理由。事实上,在rails 6.1.3之后,我认为你可以将.joins
放在.or
之前,我知道事实上你可以将.includes
放在.or
之前。至于为什么这首先存在...... Rails必须限制某些操作,如.limit
或.distinct
,因为在.or
之前允许这些操作将无法转换为sql。 (.or
将两个具有不同 .limit
s 的子句放在一起意味着什么?)这里对所有情况的更长解释:github.com/rails/rails/issues/24055#issuecomment-793274937
@nar8789 感谢这些解释。我将尽快将我的 Rails 6.0 应用程序升级到 6.1.3!
如果您想知道生成的 SQL 对于您的答案是什么样子会很有趣,因为除了工作之外,做正确的事情更重要。以上是关于传递给 #or 的关系必须在结构上兼容。不兼容的值:[:references]的主要内容,如果未能解决你的问题,请参考以下文章
将 WPARAM 传递给 DragQueryFile 不兼容?
指向整数转换的不兼容指针将“SystemSoundID”传递给“SystemSoundID”类型的参数
使用 segue 传递图像的指针类型不兼容?目标c Xcode
为 Objective-C 对象定义 DTrace 兼容结构