Проверьте, попадает ли экземпляр модели в named_scope в рельсах - PullRequest
8 голосов
/ 10 августа 2009

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

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

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

Ответы [ 2 ]

24 голосов
/ 10 августа 2009

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

Foo.bar.exists?(f)

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

1 голос
/ 18 декабря 2013

Если ваши области просты, вы, вероятно, хотите избежать дублирования кода. Мое решение позволяет вам вызывать 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. Это требует очень небольшой настройки для Rails 3 и 4. (named_scope -> scope) Я скоро проверю.

...