Skip to content
This repository

Error calling dup() on ActiveRecord model with serialized field #5797

Closed
gmcnaughton opened this Issue April 09, 2012 · 6 comments

4 participants

Gordon McNaughton Toshinori Kajihara jrreed jtokash
Gordon McNaughton

Starting with Rails >=3.2.2, I get the following error when calling dup() on a model with a serialized field:

# app/models/my_obj.rb
class MyObj < ActiveRecord::Base
  serialize :content, JSON
end
$ rails c
1.9.3-p0 :001 > MyObj.new(:content => {"a" => "b"}).dup
TypeError: can't convert Hash into String
  from gems/json-1.6.6/lib/json/common.rb:148:in `initialize'
  from gems/json-1.6.6/lib/json/common.rb:148:in `new'
  from gems/json-1.6.6/lib/json/common.rb:148:in `parse'
  from gems/json-1.6.6/lib/json/common.rb:320:in `load'
  from gems/activerecord-3.2.3/lib/active_record/attribute_methods/serialization.rb:24:in `unserialize'
  from gems/activerecord-3.2.3/lib/active_record/attribute_methods/serialization.rb:15:in `unserialized_value'
  from gems/activerecord-3.2.3/lib/active_record/attribute_methods/read.rb:82:in `__temp__'
  from gems/activerecord-3.2.3/lib/active_record/attribute_methods/read.rb:46:in `type_cast_attribute'
  from gems/activerecord-3.2.3/lib/active_record/attribute_methods/read.rb:126:in `read_attribute'
  from gems/activerecord-3.2.3/lib/active_record/attribute_methods.rb:200:in `attribute_for_inspect'
  from gems/activerecord-3.2.3/lib/active_record/base.rb:643:in `block in inspect'
  from gems/activerecord-3.2.3/lib/active_record/base.rb:641:in `collect'
  from gems/activerecord-3.2.3/lib/active_record/base.rb:641:in `inspect'
  from gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
  from gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
  from gems/railties-3.2.3/lib/rails/commands.rb:41:in `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'1.9.3-p0 :002

The above code works on Rails 3.2.1. It appears to be related to this commit for issue #4837.

The problem appears to be that after duping, the code tries to unserialize an already-unserialized value. The JSON parser chokes when it receives a Hash instead of a string.

Toshinori Kajihara kennyj referenced this issue from a commit April 10, 2012
Commit has since been removed from the repository and is no longer available.
Toshinori Kajihara
Collaborator

@gmcnaughton
I can reproduce this issue, and I fix it by the above commit (plan 1).

I guess we have new problem when merging my fix. Because I changed initialized_attributes method's signiture.

If we don't change it, I think the following code also fix it (plan 2).
What do you think ?

$ vim core.rb

def initialize_dup(other)
  cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
  serialized_attributes.each { |key, coder| cloned_attributes[key] = coder.dump(cloned_attributes[key]) } # ★added
  self.class.initialize_attributes(cloned_attributes)
  ...

cc/ @jonleighton

Gordon McNaughton

Thanks for the test case and the patch! Either solution sounds good to me, but I'll defer since I don't know the code :)

Toshinori Kajihara kennyj referenced this issue from a commit April 11, 2012
Commit has since been removed from the repository and is no longer available.
Toshinori Kajihara
Collaborator

Thanks for your confirmation !
Anyway, I sent PR :-)

jrreed
jrreed commented May 29, 2012

+1

jtokash
jtokash commented May 29, 2012

+1

Toshinori Kajihara kennyj closed this in d09b2fd May 30, 2012
Gordon McNaughton

Thanks guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.