Повторное использование named_scope для определения другого named_scope
Суть проблемы как я ее вижу
Однажды, если я не ошибаюсь, я видел пример повторного использования named_scope для определения другого named_scope. Примерно так (не могу вспомнить точный синтаксис, но это точно мой вопрос):
named_scope :billable, :conditions => ...
named_scope :billable_by_tom, :conditions => {
:billable => true,
:user => User.find_by_name('Tom')
}
Вопрос: каков точный синтаксис, если это вообще возможно? Я не могу найти его обратно, и Google тоже не помог.
Некоторые объяснения
Почему я действительно этого хочу, так это то, что я использую Searchlogic для определения сложного поиска, который может привести к выражению, подобному следующему:
Card.user_group_managers_salary_greater_than(100)
Но это слишком долго, чтобы быть повсюду. Поскольку, насколько я знаю, Searchlogic просто определяет named_scopes на лету, я хотел бы установить named_scope для класса Card следующим образом:
named_scope from_big_guys, { user_group_managers_salary_greater_than(100) }
- здесь я бы использовал этот длинный метод Searchlogic внутри моего named_scope. Но опять же, какой будет синтаксис? Не могу понять это.
Продолжить
Итак, возможно ли вложение named_scope (и я не имею в виду цепочку)?
5 ответов
Вы можете использовать proxy_options, чтобы перерабатывать один named_scope в другой:
class Thing
#...
named_scope :billable_by, lambda{|user| {:conditions => {:billable_id => user.id } } }
named_scope :billable_by_tom, lambda{ self.billable_by(User.find_by_name('Tom').id).proxy_options }
#...
end
Таким образом, он может быть связан с другими named_scopes.
Я использую это в моем коде, и он работает отлично.
Я надеюсь, что это помогает.
Рельсы 3+
У меня был тот же вопрос, и хорошая новость в том, что за последние пять лет основная команда Rails добилась определенных успехов в отделе областей.
В Rails 3+ вы можете сделать это, как и следовало ожидать:
scope :billable, where( due: true )
scope :billable_by_tom, -> { billable.where( user: User.find_by_name('Tom') ) }
Invoice.billable.to_sql #=> "... WHERE due = 1 ..."
Invoice.billiable_by_tom.to_sql #=> "... WHERE due = 1 AND user_id = 5 ..."
К вашему сведению, Rails 3+ они переименовали named_scope
чтобы просто scope
, Я также использую синтаксис Ruby 1.9.
Бонусный раунд: общий объем.
Если есть несколько человек, которые "оплачиваются", кроме "Тома", то может быть полезно создать общую область, которая принимает параметр имени, который передается в блок:
scope :billable_by, lambda { |name| billable.where( user: User.find_by_name( name ) ) }
Тогда вы можете просто позвонить с помощью:
Invoice.billable_by( "Tom" ).to_sql #=> "... WHERE due = 1 AND user_id = 5 ..."
Кстати, вы можете видеть, что я использовал старше lambda
синтаксис в бонусном раунде. Это потому, что я думаю, что новый синтаксис выглядит ужасно, когда вы передаете ему параметр: ->( name ) { ... }
,
Цепные Области.
Почему бы не иметь scope
за вещи просто Tom
в общем вроде:
scope :by_tom, where( user: User.find_by_name('Tom') )
И тогда вы можете получить те записи, которые "оплачиваются Томом" с:
Record.billable.by_tom
Вы можете использовать метод для объединения некоторых named_scope, например:
def self.from_big_guys
self.class.user_group_managers_salary_greater_than(100)
end
Эта функция добавлена в Rails 3 с новым синтаксисом ( http://m.onkey.org/2010/1/22/active-record-query-interface)