Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

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

Closed
gmcnaughton opened this Issue · 6 comments

4 participants

@gmcnaughton

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.

@kennyj kennyj referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@kennyj
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

@gmcnaughton

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 :)

@kennyj kennyj referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@kennyj
Collaborator

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

@jrreed

+1

@jtokash

+1

@kennyj kennyj closed this in d09b2fd
@gmcnaughton

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.