如何解决ActiveRecord WHERE与命名空间模型
在相同名称空间/模块中,我有两个模型:
module ReverseAuction
class Demand < ApplicationRecord
belongs_to :purchase_order,inverse_of: :demands,counter_cache: true
end
end
module ReverseAuction
class PurchaseOrder < ApplicationRecord
has_many :demands
end
end
请注意,我不必为模型指定 class_name ,因为它们位于同一模块中,并且关系以这种方式很好地工作。
当我尝试使用关系名称本身查询 includes 时,它可以正常工作,例如:
ReverseAuction::PurchaseOrder.all.includes(:demands) # all right .. AR is able to figure out that *:demands* correspond to the 'reverse_auction_demands' table
但是当我尝试在此查询中使用 where 时,AR似乎无法单独找出(命名空间)表名称,因此:
ReverseAuction::PurchaseOrder.includes(:demands).where(demands: {user_id: 1}) # gives me error: 'ERROR: missing FROM-clause entry for table "demands"'
但是,如果我指定完整的解析(命名空间)模型名称,那么哪里进行得很好:
ReverseAuction::PurchaseOrder.includes(:demands).where(reverse_auction_demands: {user_id: 1}) # works pretty well
AR 可以从 includes 中的关系推断命名空间模型的表名,但在 where ,还是我错过了重点?
解决方法
AR可以从中推断命名空间模型的表名是否正常 包含关系,但不能包含在其中?
是。这是leaky abstraction的示例。
关联是围绕SQL连接的面向对象的抽象,它使您可以做有趣的事情,而AR担心编写SQL来连接它们并维护记录之间的内存耦合。 .joins
,.left_joins
.includes
和.eager_load
“意识到”您的关联并经历了该抽象。因为您拥有这种面向对象的抽象,所以.includes
足够聪明,可以弄清楚在编写联接时模块嵌套应如何影响类名和表名。
.where
和ActiveRecord query interface的所有其他部分都不那么聪明。这只是一个以编程方式生成SQL查询的API。
当您执行.where(foo: 'bar')
时,它会很聪明,可以将其转换为WHERE table_name.foo = 'bar'
,因为该类知道其自己的表名。
当您执行.where(demands: {user_id: 1})
时,该方法实际上并不知道您的关联,其他模型类或架构,而只是生成WHERE demands.user_id = 1
,因为这是将嵌套哈希转换为SQL的方式。
请注意,这实际上与名称空间无关。当您这样做时:
.where(reverse_auction_demands: {user_id: 1})
它起作用,因为您使用的是正确的表名。如果您在使用与模型不符的非常规表名,则会遇到完全相同的问题。
如果要基于类创建一个where子句而不对表名进行硬编码,则将范围传递给where:
.where(
ReverseAuction::Demand.where(user_id: 1)
)
或使用Arel:
.where(
ReverseAuction::Demand.arel_table[:user_id].eq(1)
)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。