This project is archived and is in readonly mode.

#5381 ✓invalid
prasanna

ActiveRecord marshal dump/load has a different behavior on boolean [rails]

Reported by prasanna | August 14th, 2010 @ 07:45 PM

Step 1: setup

a = Aritcle.new(:some_boolean => false)
a.save
write_to_memcache(a.id, Marshal.dump(a))
b = Marshal.load(read_from_memcache(a.id))

If I do:

b.some_boolean = nil
b.save

the some_boolean is not written back to the DB. DB still remains false.

But:

a.some_boolean = nil
a.save

works perfectly. DB is set to NULL.

Also:

c = Article.find(a.id)
c.some_boolean = nil
c.save

works fine. DB is set to NULL.

I'm not very sure if this is a boolean specific problem, but I'm thinking rails has some private variable to detect if the record is new, and the marshal is screwing it up.

Any hints? This one was a tough nut to crack on production :) Thanks.

Comments and changes to this ticket

  • prasanna

    prasanna August 14th, 2010 @ 07:52 PM

    • Assigned user set to “Aaron Patterson”

    I was wondering if this should be a bug report of a ticket?

  • Aaron Patterson

    Aaron Patterson August 16th, 2010 @ 06:37 PM

    • State changed from “new” to “needs-more-info”
    • Importance changed from “” to “Low”

    I can't seem to reproduce this problem. What database are you using? What version of Rails? Can you share your schema?

    Even better would be if you could supply a small rails app that reproduces the problem. I would really appreciate that! :-D

    I've tried adding the following test to the AR test cases, but cannot reproduce the problem:

    class Booleantest < ActiveRecord::Base; end
    
    def test_saving_after_marshal
      bool = Booleantest.new(:value => false)
      bool = Marshal.load Marshal.dump bool
      bool.value = nil
      bool.save
      bool.reload
      assert_nil bool.value
    end
    
  • prasanna

    prasanna August 16th, 2010 @ 08:11 PM

    DataBase: mysql
    Rails: 2.3.5

    To reproduce it: You have to put the following statement in your after_save handler.

    class Bool
    
      after_save :dumper
    
      def dumper
        $global = Marshal.load Marshal.dump self
      end
    
    end
    
    Bool.new(:value => false).save
    puts $global.value # is false -> OK
    
    $global.value = nil
    $global.save
    puts $global.value # is nil -> OK
    
    $global.reload
    puts $global.value # is false -> BAD
    

    I owe you an apology for not testing Marshal.load Marshal.dump sequence. I was binary-searching the problem and this is what I got it down to. If you need any more info, or if you are unable to reproduce this, feel free to ping me. myprasanna@gmail.com

  • prasanna

    prasanna August 16th, 2010 @ 08:21 PM

    It is probably not a deal-breaker. I am guessing, rails works like this:

    
    @after_save_running = true
    # call the after_save handlers
    @after_save_running = false
    

    And since I dump in the after_save handler, that variable gets dumped as true. The next time I try to save it fails, to do it, thinking the after_save handler is calling a save function, causing recursion. I think you can safely close this.

    Thanks for your time.

  • Aaron Patterson

    Aaron Patterson November 4th, 2010 @ 10:10 PM

    • State changed from “needs-more-info” to “invalid”
  • bingbing

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages