Вложенные области видимости в Rails 3.1 - PullRequest
3 голосов
/ 19 ноября 2011

Есть ли способ, которым я могу преобразовать метод to_be_approved в следующем коде в область, которая использует две другие области?

scope :reports_to, lambda { |manager| 
  joins(" JOIN admin_users request_user on requests.admin_user_id = request_user.id and request_user.manager_id = #{manager.id} ") }
scope :pending, joins(:admin_request_status).where('admin_request_statuses.name = ?','Pending Approval')

def self.to_be_approved_by( manager )
  reports_to(manager).pending
end

Я также хочу избавиться от встроенного sql в области reports_to, но это совсем другой вопрос:)

1 Ответ

10 голосов
/ 19 ноября 2011
scope :reports_to, lambda { |manager| joins(:admin_user).where('admin_users.manager_id = ?',manager.id) }  
scope :pending, joins(:admin_request_status).where('admin_request_statuses.name = ?','Pending Approval')
scope :to_be_approved_by, lambda { |manager| self.pending.reports_to(manager) }
end

Примечание для всех.

Подобные цепочки областей обычно нормальны с точки зрения производительности, потому что «внешняя» или «начальная» область не будет оцениваться до тех пор, пока в примере не будет вызвана полная цепочка областей действия (например, scope_name1.scope_name2.scope_name3 и т. Д. И только когда фактический вывод необходим, если будет построен sql. Это известно как «отложенная загрузка» , например, «Будьте ленивыми, не создавайте результаты, пока они не потребуются».

Это в отличие от "нетерпеливой загрузки" , где вы используете оператор: include для получения других таблиц и выполнения множественных запросов "за один раз" и избегаете печально известной проблемы "n + 1", которая где программа завершает выполнение (например) 101 запроса, чтобы получить 100 записей.

Много интересной информации:)

...