【问题标题】:ActiveRecord WHERE with namespaced models带有命名空间模型的 ActiveRecord WHERE
【发布时间】:2020-09-23 19:33:26
【问题描述】:

我在相同的命名空间/模块中有两个模型:

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"'

但是如果我指定完整的解析(命名空间)模型名称,那么 where 会很顺利:

ReverseAuction::PurchaseOrder.includes(:demands).where(reverse_auction_demands: {user_id: 1}) # works pretty well

AR可以includes中的关系推断命名空间模型的表名但不能where,还是我没抓住重点?

【问题讨论】:

    标签: ruby-on-rails ruby activerecord ruby-on-rails-6


    【解决方案1】:

    AR 可以从中推断命名空间模型的表名是否正常? 包含但不能在 where 中的关系?

    是的。这是leaky abstraction 的示例。

    关联是围绕 SQL 连接的面向对象的抽象,让您可以做一些有趣的事情,而 AR 则担心编写 SQL 来连接它们并维护记录之间的内存耦合。 .joins.left_joins .includes.eager_load 都“意识到”您的关联并通过该抽象。因为你有这个面向对象的抽象.includes 足够聪明,可以在编写连接时弄清楚模块嵌套应该如何影响类名和表名。

    .whereActiveRecord 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)
    )
    

    【讨论】:

    • 这是一个很好的解释...我对此非常满意...谢谢@max
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    相关资源
    最近更新 更多