ActiveRecord объединяет текущие где условия при применении области?

Я столкнулся с неожиданным поведением в 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 обнуляется, последнее объединяется в слиянии:

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 пункты после применения моей сферы.)

2 ответа

Решение

Эта суть подводит итог наших выводов по этому вопросу. https://gist.github.com/kirel/5678865

Сводится к ActiveRecord::Scoping::Named::ClassMethods#scope с помощью ActiveRecord::SpawnMethods#merge который реализует неожиданное, но предполагаемое поведение.

Rails 4 не будет использовать слияние и, следовательно, вести себя как положено (см. https://github.com/rails/rails/commit/cd26b6ae7c1546ef8f38302661bbedf8cb487311). Между тем, обходной путь - просто избегать области видимости и использовать вместо этого методы класса.

Измените это на

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

Кажется, что когда вы использовали scope после where предложение просто создайте новый хеш из предложения цепочки where и затем AND в конце.

следовательно

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)"
Другие вопросы по тегам