I made a real basic github project here that demonstrates the issue. Basically, when I create a new comment, it is saved as expected; when I update an existing comment, it isn't saved. However, that isn't what the docs for :autosave => true
say ... they say the opposite. Here's the code:
class Post < ActiveRecord::Base
has_many :comments,
:autosave => true,
:inverse_of => :post,
:dependent => :destroy
def comment=(val)
obj=comments.find_or_initialize_by(:posted_at=>Date.today)
obj.text=val
end
end
class Comment < ActiveRecord::Base
belongs_to :post, :inverse_of=>:comments
end
Now in the console, I test:
p=Post.create(:name=>'How to groom your unicorn')
p.comment="That's cool!"
p.save!
p.comments # returns value as expected. Now we try the update case ...
p.comment="But how to you polish the rainbow?"
p.save!
p.comments # oops ... it wasn't updated
Why not? What am I missing?
Note if you don't use "find_or_initialize", it works as ActiveRecord respects the association cache - otherwise it reloads the comments too often, throwing out the change. ie, this implementation works
def comment=(val)
obj=comments.detect {|obj| obj.posted_at==Date.today}
obj = comments.build(:posted_at=>Date.today) if(obj.nil?)
obj.text=val
end
But of course, I don't want to walk through the collection in memory if I could just do it with the database. Plus, it seems inconsistent that it works with new object but not an existing object.
Here is another option. You can explicitly add the record returned by find_or_initialize_by
to the collection if it is not a new record.
def comment=(val)
obj=comments.find_or_initialize_by(:posted_at=>Date.today)
unless obj.new_record?
association(:comments).add_to_target(obj)
end
obj.text=val
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With