【问题标题】:ActiveRecord .exists?() and default_scope weirdnessActiveRecord .exists?() 和 default_scope 怪异
【发布时间】:2023-04-08 12:31:01
【问题描述】:

我们的 User 类上有一个 default_scope,它将用户限制为一组公司:

class User < ActiveRecord::Base
  default_scope do
    c_ids = Authorization.current_company_ids
    includes(:companies).where(companies: { id: c_ids })
  end

  has_many :company_users
  has_many :companies, through: company_users
end

class CompanyUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :company
  validates_uniqueness_of :company_id, scope: :user_id
end

class Company < ActiveRecord::Base
  has_many :company_users
  has_many :users, through: company_users
end

调用 User.lastUser.find_by_email('mhayes@widgetworks.com')User.find(55557) 所有工作和范围都按预期进行。

调用User.exists?(id) 会抛出一个奇怪的错误:

Mysql2::Error: Unknown column 'companies.id' in 'where clause': SELECT  1 AS one FROM `users`  WHERE `companies`.`id` IN (4) AND `users`.`id` = 55557 LIMIT 1

基本上,如果我得到这个,那就是说companies 不是User 上的一个列,它是。如果我什至将 sql 复制到 where 语句中,它的计算结果是正确的。

User.where("SELECT  1 AS one FROM `users`  WHERE `companies`.`id` IN (4) AND `users`.`id` = 66668 LIMIT 1")

这让我觉得default_scope 的评估顺序和exists?default_scope 之前以某种方式被调用。

如果我打电话:

User.includes(:companies).where(companies: { id: [4] }).exists?(55557)

有效。这就是 default_scope 正在做的事情,所以我知道 default_scope 范围没有失败。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord exists default-scope


    【解决方案1】:

    老实说,我不知道,但在我看来,exists? 直接建立了一个关系,并决定放弃includes 子句,因为exists? 认为它没有需要加载其他对象。这发生在this method call。而链式 exists? 已经通过构建较早的关系(其中includes 转换为joins)正确计算了它。

    也许不是一个错误,但可能是另一个奇怪的东西,用default_scope 添加到列表中。

    可能最好的解决方案是将default_scope 中的includes 变为实际的joins,并在您实际需要完整记录时手动调用includes。 (因为您实际上并不需要它们来进行exists? 通话)

    另一种可能性是在default_scope 中同时链接includesjoins。我不知道这对arel 计算有什么影响,尽管我很怀疑。 可能有效,也可能无效。

    或者,如果你真的希望它在整体上保持不变,你可以做一些疯狂的事情,比如:

    def self.exists?(args)
      self.scoped.exists?(args)
    end
    

    这将基本上建立一个具有默认范围的 relation,然后在已执行 includes 的已构建 relation 上调用 exists? -> joins 魔术.

    【讨论】:

    • 是的。在default_scope 工作中链接includesjoins
    【解决方案2】:

    试试这个

    User.exists?(id: 55557)
    

    【讨论】:

    • 是的。这会引发错误Mysql2::Error: Unknown column 'companies.id' in 'where clause': SELECT 1 AS one FROM users` WHERE companies.id IN (4) AND users.id = 55557 LIMIT 1`
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多