2

我在 Active Record (3.2.13) 中遇到了一些意外行为:

我的模型上有一个简单的范围:

class User < ActiveRecord::Base
  scope :verified, lambda { where('verified = 1') }
end

这可以单独使用:

  User.verified.to_sql
  #=> "SELECT \"users\".* FROM \"users\"  WHERE (verified = 1)"

当我连接where- 子句时,它们会and按预期进行编辑:

  User.where(company_id: 1).where(company_id: 2).to_sql
  "SELECT \"users\".* FROM \"users\"  WHERE \"users\".\"company_id\" = 1 AND \"users\".\"company_id\" = 2"

问题:

但是,当我链接一个范围时,我的第一个 where 子句是 nuked,最后一个在合并中获胜:

User.where(company_id: 1).where(company_id: 2).verified.to_sql
"SELECT \"users\".* FROM \"users\"  WHERE \"users\".\"company_id\" = 2 AND (verified = 1)"

如何在与现有条件的关系上应用范围?

(这些现有条件是通过康康建立的load_and_authorize_resource,所以我不能在应用我的范围where只应用这些条款。)

4

2 回答 2

2

这个要点总结了我们在这个问题上的发现。https://gist.github.com/kirel/5678865

它归结为ActiveRecord::Scoping::Named::ClassMethods#scopeusing ActiveRecord::SpawnMethods#mergewhich 实现了意外但预期的行为。

Rails 4 不会使用合并,因此会按预期运行(请参阅https://github.com/rails/rails/commit/cd26b6ae7c1546ef8f38302661bbedf8cb487311)。同时,解决方法是避免作用域并改用类方法。

于 2013-05-30T15:54:59.303 回答
1

将其更改为

User.verified.where(company_id: 1).where(company_id: 2).to_sql

似乎当您scopewhere子句之后使用它时,它只是创建了链式 where 子句的新哈希,然后在最后加上它。

因此

User.where(company_id: 1).where(company_id: 2).verified.to_sql

给你

"SELECT \"users\".* FROM \"users\"  WHERE \"users\".\"company_id\" = 2 AND 
(verified = 1)"

User.where(company_id: 1).where(contact_id: 2).verified.to_sql

给你

"SELECT \"users\".* FROM \"users\"  WHERE \"users\".\"company_id\" = 2 AND
\"users\".\"contact_id\" = 2 AND (verified = 1)"
于 2013-05-30T09:57:54.857 回答