Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

Closed
gmcnaughton opened this Issue · 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
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
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

+1

jtokash

+1

Toshinori Kajihara kennyj closed this in d09b2fd
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.