I’m adding caching to my Rails app and one of the things I’m doing is instantiating an ActiveRecord model using the .new method (instead of .create) so it doesn’t try to create a new row.
For example, if I add this to my model:
def from_json(json)
o = self.new
ActiveSupport::JSON.decode(json).each do |k, v|
# NOTE: I am doing this instead of sending all the params to .new
# because Rails won't let me bulk update protected attributes
o.send(k + '=', v)
end
o
end
And then instantiate an object from the cache:
o = Foo.from_json(redis.get(key))
Everything seems to work well until I try to change a field:
o.bar = "spam and eggs"
o.save
I get an exception saying that this is a duplicate entry.
How do I tell ActiveRecord that this actual refers to the row that already exists in the database so that it updates that row instead of throwing and exception?
The answers I needed were found in
lib/active_record/base.rb. I need to initialize the object withnew_recordset tofalseand the way to do this was to allocate the object and then initialize it withinit_with. Note that you need to properly serialize the specialserialized_attributesusing their defined coders.Note that I am using Rail 3.1.