Проверьте, попадает ли экземпляр модели в именованную область в rails


Предположим, что у меня есть именованная область:

class Foo < ActiveRecord::Base
    named_scope :bar, :conditions => 'some_field = 1'
end

Это отлично работает для запросов, и у меня есть куча полезных named_scopes, определенных. Что я хотел бы иметь возможность сделать это:

f = Foo.find(:first)
f.some_field = 1
f.is_bar? #=> true

The '.бар? метод просто возвращает true или false, если экземпляр модели попадает в именованную область. Есть ли вообще возможность сделать это, не написав "is_bar_"?"метод, хотя я уже написал хороший способ проверить, есть ли что-то" is_bar_?- Если я правильно помню, сухой-это хорошо, так что любая помощь будет весьма признателен/

2 7

2 ответа:

Можно вызвать метод exists? в именованной области, который будет запрашивать базу данных, чтобы увидеть, существует ли данная запись с этими условиями.

Foo.bar.exists?(f)

Однако это не будет работать, если вы изменили атрибуты на f и не сохранили его в базе данных. Это происходит потому, что именованные условия области являются SQL, поэтому проверка должна происходить там. Попытка преобразования в Ruby if условия является беспорядочной, особенно в более сложных сценариях.

Если ваши области просты, вы, вероятно, хотите избежать дублирования кода. Мое решение позволяет вызвать model.active?, чтобы узнать, принадлежит ли экземпляр области, и Model.active, чтобы найти все записи, соответствующие области. model.active? не включает никаких запросов к базе данных.

Подумайте о том, чтобы добавить это к config/initializers/scope_and_method.rb:

require 'active_record/named_scope'

module ActiveRecord::NamedScope::ClassMethods
  def scope_and_method field, *values
    field = field.to_sym
    values.each do |value|
      named_scope value.to_sym, :conditions => {field => value}
      define_method "#{value}?" do
        send(field.to_sym) == value
      end
    end
  end
end

Использование:

scope_and_method :state, 'active', 'inactive'

Работает так, как если бы это было:

named_scope :active, :conditions => {:state => 'active'}
named_scope :inactive, :conditions => {:state => 'inactive'}

def active?
  state == 'active'
end

def inactive?
  state == 'inactive'
end

Это решение для Rails 2.3. Это требует очень небольшой настройки для рельсов 3 и 4. (named_scope -> scope) я это проверю. скоро.