我在相同的命名空间/模块中有两个模型:
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可以从中的关系中推断出名称空间模型的表名,但不能在的中这正常吗?还是我没有抓住要点?
AR可以从includes中的关系,但不能在中?
是这是一个泄漏抽象的例子。
Assocations是一种围绕SQL连接的面向对象的抽象,让您可以在AR担心编写SQL来连接它们以及维护记录之间的内存耦合时做一些有趣的事情。.joins
、.left_joins
、.includes
和.eager_load
是"0";意识到";你的联想,并通过抽象。因为有了这种面向对象的抽象,.includes
足够聪明,可以在编写联接时弄清楚模块嵌套应该如何影响类名和表名。
.where
和ActiveRecord查询接口的所有其他部分都不那么智能。这只是一个以编程方式生成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)
)