Повторное использование 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 ответов

Решение

Обратитесь к этому вопросу, поднятому некоторое время назад здесь, на SO. На маяке есть патч для выполнения ваших требований.

Вы можете использовать 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)

Другие вопросы по тегам