If you're working with ActiveRecord models, don't forget that you can do your selection at the database level, rather than in memory. To rephrase, you can retrieve from the database only the values that you want into your array, and then simply change those.
Here's an example using custom finders (sort of an older way to do it):
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! }
Or you could do it with another association:
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! }
Here's another example using named scopes (a little newer, and preferred in my opinion) on your child class:
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! }
But in any of the cases, you've abstracted the "selection", which has a few benefits:
- Faster in cases of large collections
- You've abstracted the lower level selection criteria to something with higher level semantic meaning, which makes your code easier to read and maintain