Именованные области видимости могут быть объединены в цепочку, так что вы делаете это для себя сложнее, чем нужно.
Следующее определение в пользовательской модели даст вам то, что вы хотите:
class User < ActiveRecord::Base
...
named_scope :filter_by_name, lambda { |name|
{:conditions => { :name => name} }
}
named_scope :active, :conditions => {:active => true}
named_scope :inactive, :conditions => {:active => false}
named_scope :have_logged_in, :conditions => {:logged_in => true}
end
Тогда будут работать следующие фрагменты:
active_users = Project.find(1).users.active
some_users = active_users.filter_by_name( ["Pete", "Alan"]
other_users = active_users.filter_by_name "Rob"
logged_in_users = Project.find(1).users.have_logged_in
more_users = logged_in_users.filter_by_name "John"
Я вижу, что вы используете detect
, вероятно, чтобы избежать лишних попаданий в БД. Но ваши примеры не используют это должным образом. Detect возвращает только первый элемент в списке, для которого блок возвращает true. В приведенном выше примере some_users
будет только одной записью, первым пользователем с именем «Пит» или «Алан». Если вы хотите, чтобы все пользователи назывались «Пит» или «Алан», тогда вам нужно select
. А если вы хотите select
, то лучше использовать именованную область.
Именованные области при оценке возвращают специальный объект, содержащий компоненты, необходимые для построения оператора SQL для генерации результатов, при этом цепочка других именованных областей все еще не выполняет инструкцию. Пока вы не попытаетесь получить доступ к методам в наборе результатов, таким как вызов каждого или карты.