public
Last active

ActiveRecord::Base doesn't serialize instance variables

  • Download Gist
gistfile1.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
~/Code/playground/rails-3-2-stable $ cat app/models/person.rb
class Person
attr_accessor :abc
end
 
 
~/Code/playground/rails-3-2-stable $ cat app/models/story.rb
class Story < ActiveRecord::Base
attr_accessor :abc
end
 
~/Code/playground/rails-3-2-stable $ cat app/models/user.rb
class User < ActiveRecord::Base
attr_accessor :abc
 
def encode_with(coder)
super
coder['abc'] = abc
end
 
def init_with(coder)
super
@abc = coder['abc']
self
end
end
 
 
~/Code/playground/rails-3-2-stable $ bundle exec rails c
Loading development environment (Rails 3.2.2)
# Person is a plain old ruby object which serializes instance variables correctly in 1.9.3:
1.9.3p125 :001 > Person.new.tap {|p| p.abc = 123}
=> #<Person:0x007fd325c07290 @abc=123>
1.9.3p125 :002 > Person.new.tap {|p| p.abc = 123}.abc
=> 123
1.9.3p125 :003 > Person.new.tap {|p| p.abc = 123}.to_yaml
=> "--- !ruby/object:Person\nabc: 123\n"
1.9.3p125 :004 > YAML.load(Person.new.tap {|p| p.abc = 123}.to_yaml)
=> #<Person:0x007fd325cdfcd0 @abc=123>
1.9.3p125 :005 > YAML.load(Person.new.tap {|p| p.abc = 123}.to_yaml).abc
=> 123
 
# Story is a ActiveRecord::Base object which only serializes @attributes but not instance variables
# (see: https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/base.rb#L582)
1.9.3p125 :001 > Story.new.tap {|s| s.abc = 123}
=> #<Story id: nil, type: nil, name: nil, created_at: nil, updated_at: nil>
1.9.3p125 :002 > Story.new.tap {|s| s.abc = 123}.abc
=> 123
1.9.3p125 :003 > Story.new.tap {|s| s.abc = 123}.to_yaml
=> "--- !ruby/object:Story\nattributes:\n id: \n type: \n name: \n created_at: \n updated_at: \n"
1.9.3p125 :004 > YAML.load(Story.new.tap {|s| s.abc = 123}.to_yaml)
=> #<Story id: nil, type: nil, name: nil, created_at: nil, updated_at: nil>
1.9.3p125 :005 > YAML.load(Story.new.tap {|s| s.abc = 123}.to_yaml).abc
=> nil
 
# User is a ActiveRecord::Base object which has a custom encode_with and init_with methods to
# properly serialize the abc instance variable.
1.9.3p125 :001 > User.new.tap {|u| u.abc = 123}
=> #<User id: nil, type: nil, name: nil, created_at: nil, updated_at: nil>
1.9.3p125 :002 > User.new.tap {|u| u.abc = 123}.abc
=> 123
1.9.3p125 :003 > User.new.tap {|u| u.abc = 123}.to_yaml
=> "--- !ruby/object:User\nattributes:\n id: \n type: \n name: \n created_at: \n updated_at: \nabc: 123\n"
1.9.3p125 :004 > YAML.load(User.new.tap {|u| u.abc = 123}.to_yaml)
=> #<User id: nil, type: nil, name: nil, created_at: nil, updated_at: nil>
1.9.3p125 :005 > YAML.load(User.new.tap {|u| u.abc = 123}.to_yaml).abc
=> 123

Hi jrafanie,

You saved us a lot of time running around tweaking between delayed_jobs 2 (uses syck yaml parser) and delayed_jobs 3 (uses psych yaml parser). In the older version we persisted attr_accessors but the newer version doesn't care about them. So we applied your style of overriding encode_with and init_with methods to add attr_accessors to the coder hash and that took care of Psych parser's behavior of being ignorant towards instance variables.
Thanks you so much!

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.