Skip to content

Instantly share code, notes, and snippets.

@jrafanie
Created June 28, 2012 13:49
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jrafanie/3011499 to your computer and use it in GitHub Desktop.
Save jrafanie/3011499 to your computer and use it in GitHub Desktop.
ActiveRecord::Base doesn't serialize instance variables
~/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
@pmanda-carecloud
Copy link

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment