After doing some poking around, it looks like it is a little more complicated than that.
My poking around went like this:
- I created a pair of models, Parent
and Child with a
has_many
relationship in a throwaway rails
app.
- I opened up
script/console
and
poked around.
I created a new parent with a child and saved them
>> p = Parent.new;p.children << Child.new(:foo=>'bar');p.save
=> true
See the child is in the db and findable by_foo
>> p.children.find_by_foo('bar')
=> #<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">
I added another child to the collection,it shows up in p.children
but not in collection methods that hit the db.
>> p.children << Child.new(:foo=>'bar')
=> [#<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">, #<Child id: 2, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:25", updated_at: "2009-12-14 22:08:25">]
>> p.children.find_by_foo('bar')
=> #<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">
I change the child that is in the db.
>> p.children[0].foo = 'baz'
=> "baz"
When I search for it, it gives me the db version.
>> p.children.find_by_foo('bar')
=> #<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">
But, the local collection is unchanged.
>> p.children
=> [#<Child id: 1, foo: "baz", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">, #<Child id: 2, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:25", updated_at: "2009-12-14 22:08:25">]
So if you save p again, it will pass on the changes.
If you want to get all the local association objects, including ones that have been changed, you can't use the ActiveRecord finders because they hit the db, instead use array methods like you did above. Though, using find_all
or select
would be easier to understand
parent.children.select{|c| c.attr == 'foo'}