Если вы работаете с моделями ActiveRecord, не забывайте, что вы можете делать выбор на уровне базы данных, а не в памяти. Чтобы перефразировать, вы можете извлечь из базы данных только те значения, которые вам нужны, и затем просто изменить их.
Вот пример использования пользовательских средств поиска (своего рода более старый способ сделать это):
class Question < ActiveRecord::Base
has_many :answers do
def accepted
find :all, :conditions => { :accepted => true }
end
end
end
class Answer < ActiveRecord::Base
belongs_to :question
end
q = Question.find :first
q.answers.accepted.each { |a| a.do_something! }
Или вы можете сделать это с другой ассоциацией:
class Question < ActiveRecord::Base
has_many :answers
has_many :accepted_answers, :class_name => "Answer", :conditions => { :accepted => true }
end
class Answer < ActiveRecord::Base
belongs_to :question
end
q = Question.find :first
q.accepted_answers.each { |a| a.do_something! }
Вот еще один пример использования именованных областей (немного новее и предпочтительнее, на мой взгляд) в вашем дочернем классе:
class Question < ActiveRecord::Base
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :question
named_scope :accepted, :conditions => { :accepted => true }
end
q = Question.find :first
q.answers.accepted.each { |a| a.do_something! }
Но в любом случае вы абстрагировали «подбор», который имеет несколько преимуществ:
- Быстрее в случае больших коллекций
- Вы абстрагировали критерии выбора более низкого уровня к чему-то с семантическим значением более высокого уровня, что упрощает чтение и поддержку вашего кода