Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails associations :autosave doesn't seem to working as expected

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.

like image 376
Rob Avatar asked Sep 26 '22 20:09

Rob


1 Answers

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
like image 182
John Naegle Avatar answered Oct 11 '22 14:10

John Naegle