Как уже упоминалось выше, активные записи ассоциации создать метрику buttload методов удобства. Конечно, вы могли бы написать свои собственные методы, чтобы получить все. Но это не путь Rails.
The Rails Way является кульминацией двух девизов. DRY (не повторяйте себя) и «Конвенция по конфигурации». По сути, обозначая вещи таким образом, что имеет смысл, некоторые надежные методы, предоставляемые структурой, могут абстрагировать весь общий код. Код, который вы размещаете в своем вопросе, является прекрасным примером того, что можно заменить одним вызовом метода.
Где эти удобные методы действительно блестят, это более сложные ситуации. То, что связано с моделями присоединения, условиями, валидациями и т. Д.
Чтобы ответить на ваш вопрос, когда вы делаете что-то вроде @user.articles.find(:all, :conditions => ["created_at > ? ", tuesday])
, Rails готовит два SQL-запроса, а затем объединяет их в один. где, когда ваша версия просто возвращает список объектов. Именованные области делают то же самое, но обычно не пересекают границы модели.
Вы можете проверить его, проверив SQL-запросы в development.log, как вы это называете в консоли.
Так что давайте поговорим о Named Scopes на мгновение, потому что они дают отличный пример того, как рельсы обрабатывают SQL, и я думаю, что это более простой способ продемонстрировать, что происходит за кулисами, поскольку они не нуждаются в каких-либо модельных ассоциаций.
Именованные области могут использоваться для выполнения пользовательских запросов модели. Их можно связать вместе или даже позвонить через ассоциации. Вы можете легко создавать пользовательские поисковые устройства, которые возвращают идентичные списки, но затем вы сталкиваетесь с теми же проблемами, что и в Вопросе.
class Article < ActiveRecord::Base
belongs_to :user
has_many :comments
has_many :commentators, :through :comments, :class_name => "user"
named_scope :edited_scope, :conditions => {:edited => true}
named_scope :recent_scope, lambda do
{ :conditions => ["updated_at > ? ", DateTime.now - 7.days]}
def self.edited_method
self.find(:all, :conditions => {:edited => true})
end
def self.recent_method
self.find(:all, :conditions => ["updated_at > ?", DateTime.now - 7 days])
end
end
Article.edited_scope
=> # Array of articles that have been flagged as edited. 1 SQL query.
Article.edited_method
=> # Array of Articles that have been flagged as edited. 1 SQL query.
Array.edited_scope == Array.edited_method
=> true # return identical lists.
Article.recent_scope
=> # Array of articles that have been updated in the past 7 days.
1 SQL query.
Article.recent_method
=> # Array of Articles that have been updated in the past 7 days.
1 SQL query.
Array.recent_scope == Array.recent_method
=> true # return identical lists.
Вот где все меняется:
Article.edited_scope.recent_scope
=> # Array of articles that have both been edited and updated
in the past 7 days. 1 SQL query.
Article.edited_method.recent_method
=> # no method error recent_scope on Array
# Can't even mix and match.
Article.edited_scope.recent_method
=> # no method error
Article.recent_method.edited_scope
=> # no method error
# works even across associations.
@user.articles.edited.comments
=> # Array of comments belonging to Articles that are flagged as
edited and belong to @user. 1 SQL query.
По существу каждый Именованная создает фрагмент SQL. Rails будет умело сливаться со всеми остальными фрагментами SQL в цепочке, чтобы создать один запрос, сохраняющий именно то, что вы хотите. Методы, добавленные методами ассоциации, работают одинаково. Именно поэтому они легко интегрируются с named_scopes.
Причина смешивания & Совпадение не работает, это то же самое, что метод of_sector, определенный в вопросе, не работает. edit_methods возвращает массив, где, как отредактированный_scope (а также поиск и все другие методы удобства AR, называемые частью цепочки), передают свой SQL-фрагмент дальше к следующей вещи в цепочке. Если он последний в цепочке, он выполняет запрос. Точно так же это не сработает.
@edited = Article.edited_scope
@edited.recent_scope
Вы пытались использовать этот код.Вот правильный способ сделать это:
class User < ActiveRecord::Base
has_many :articles do
def of_sector(sector_id)
find(:all, :conditions => {:sector_id => sector_id})
end
end
end
Для достижения этой функции вы хотите сделать это:
class Articles < ActiveRecord::Base
belongs_to :user
named_scope :of_sector, lambda do |*sectors|
{ :conditions => {:sector_id => sectors} }
end
end
class User < ActiveRecord::Base
has_many :articles
end
Затем вы можете сделать что-то вроде этого:
@user.articles.of_sector(4)
=> # articles belonging to @user and sector of 4
@user.articles.of_sector(5,6)
=> # articles belonging to @user and either sector 4 or 5
@user.articles.of_sector([1,2,3,])
=> # articles belonging to @user and either sector 1,2, or 3
Этот один '/ (^ __ |^nil \? $ |^Send $ | proxy_ |^object_id $) /' так смешно, что я больше не боюсь регулярных выражений. – jibiel