Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

ActiveRecord serialization throws SerializationTypeMismatch if I try to serialize a AR object

#6109

Hi there,

I have an issue with the ActiveRecord serialization in Rails 3.0.3 (Ruby 1.8.7 and 1.9.2):

Given two ActiveRecord models:

class User < ActiveRecord::Base
  # has one string column 'name'
end

class Invoice < ActiveRecord::Base
  serialize :user, User
end

When I run the following code it throws an exception

User.create! :name => 'Foo Bar'
Invoice.create! :user => User.last

Invoice.last
# throws:
# 'ActiveRecord::SerializationTypeMismatch: user was supposed to be a User, but was a String'

I'm not sure if this just an understanding issue from my side (serializing arbitrary non-AR classes works fine), or if this really a bug. Is it not possible to serialize AR classes? Currently I'm working with a workaround, that rebuilds the object from a serialized attributes hash, but I thought that serialize would do this already.

Any help to clarify this is really appreciated and thank you in advance for your effort.

Reported by rmehner · December 3rd, 2010 @ 10:44 AM

State: resolved
Milestone: none
Assigned to: nobody
Importance: Low

Activity

  1. Neeraj Singh
    Neeraj Singh
    • Importance changed from to Low

    I am not able to reproduce this problem in Rails edge.

    class Brake < ActiveRecord::Base
    
      serialize :car, Car
    
    end
    
    ree-1.8.7-2010.02 > Car.create! :name => 'honda'
       (0.2ms)   SELECT name
     FROM sqlite_master
     WHERE type = 'table' AND NOT name = 'sqlite_sequence'
    
      AREL (0.3ms)  INSERT INTO "cars" ("name") VALUES ('honda')
     => #<Car id: 1, name: "honda"> 
    ree-1.8.7-2010.02 > Brake.create! :car => Car.last
      Car Load (0.3ms)  SELECT "cars".* FROM "cars" ORDER BY cars.id DESC LIMIT 1
      AREL (0.5ms)  INSERT INTO "brakes" ("car") VALUES ('--- !ruby/object:Car 
    attributes: 
     name: honda
     id: 1
    attributes_cache: {}
    
    changed_attributes: {}
    
    destroyed: false
    marked_for_destruction: false
    new_record: false
    previously_changed: {}
    
    readonly: false
    ')
     => #<Brake id: 1, car: #<Car id: 1, name: "honda">> 
    ree-1.8.7-2010.02 > Brake.last
      Brake Load (0.4ms)  SELECT "brakes".* FROM "brakes" ORDER BY brakes.id DESC LIMIT 1
     => #<Brake id: 1, car: #<Car id: 1, name: "honda">> 
    ree-1.8.7-2010.02 >
    

    December 4th, 2010 @ 09:25 AM

  2. newpowerbiz
  3. rmehner
    rmehner

    Thank you Neeraj,

    it's indeed fixed in Edge Rails. Unfortunately not in the stable releases.

    Thank you for pointing me to the right direction and for your effort.

    Greetings,
    - Robin

    December 4th, 2010 @ 05:52 PM

  4. Neeraj Singh
    Neeraj Singh
    • State changed from new to resolved

    December 4th, 2010 @ 05:59 PM

  5. Bob Lail
    Bob Lail
    • Tag set to workaround yaml serialize 3.0.3 issue

    A workaround for Rails 3.0.3:

    I spent a while scanning through commit between July 28 and December 4 and could not find a patch that atomically fixed this.

    If you need to stay on the stable brach for the time being, this can serve as a workaround. Change this:

      def []=(key, value)
        @keys << key unless has_key?(key)
        super
      end
    

    to this:

      def []=(key, value)
        (@keys||=[]) << key unless has_key?(key)
        super
      end
    

    in active_support/ordered_hash.rb. I know it's kind of ugly, but it's the smallest change that resolves the issue.

    January 11th, 2011 @ 05:11 PM

  6. Bob Lail
    Bob Lail

    BTW, a short test for the problem is:

    YAML.load "--- \n- &id001 !ruby/object:MonthlyOccurrence \n errors: !ruby/object:ActiveModel::Errors\n base: *id001\n hash: {}\n\n kind: day\n ordinal: 1"

    This works on Rails 2.3.9 and fails on Rails 3.0.3. (You don't need to have a MonthlyOccurrence class defined in your project for YAML.load to work.) The stack trace shows there to be an issue deserializing OrderedHash, which is superclass of ActiveModel::Errors.

    January 11th, 2011 @ 05:15 PM