Повторное использование named_scope для определения другого named_scope - PullRequest
7 голосов
/ 14 марта 2010

Суть проблемы, как я ее вижу

Однажды, если я не ошибаюсь, я видел пример повторного использования 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 ]

7 голосов
/ 20 июля 2010

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

Я использую это в своем коде, и он отлично работает.

Надеюсь, это поможет.

2 голосов
/ 13 апреля 2015

Рельсы 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 ) { ... }.

1 голос
/ 30 мая 2015

Цепные Области.

Почему бы не иметь scope для вещей просто на Tom в целом, например:

scope :by_tom, where( user: User.find_by_name('Tom') )

И тогда вы можете получить те записи, которые «оплачиваются Томом» с помощью:

Record.billable.by_tom
1 голос
/ 15 марта 2010

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

0 голосов
/ 14 марта 2010

Вы можете использовать метод для объединения некоторых 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)

...