This project is archived and is in readonly mode.

#340 ✓stale
railsgeek

YAML, ActiveRecord Serialize and Date formats problem

Reported by railsgeek | June 5th, 2008 @ 01:39 PM

I'm spanish, and was using DATE_FORMATS to allow correct spanish format of date values. I'm using this at environment.rb file:

ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS[:default] = '%d-%m-%Y'

But using serialize of attributes in ActiveRecord classes give me problems. I have a simple model like that:

class History < ActiveRecord::Base serialize :changes end

Doing this:

History.create({:changes=>{:my_date=>Date.today}})

I can't read changes attribute like an Hash object, it always return a String object.

Digging deeper,..., I have found that the problem resides on the YAML library and the format of Date type.

Doing this:

Date.today.to_yaml => "--- !timestamp 05-06-2008\n"

But doing this:

YAML.load(Date.today.to_yaml) ArgumentError: argument out of range

    from /usr/lib/ruby/1.8/yaml.rb:133:in `utc'
    from /usr/lib/ruby/1.8/yaml.rb:133:in `node_import'
    from /usr/lib/ruby/1.8/yaml.rb:133:in `load'
    from /usr/lib/ruby/1.8/yaml.rb:133:in `load'
    from (irb):1

Reading the YAML Cookbook at http://yaml4r.sourceforge.net/co... I have found that YAML needs Date to be represented by its year, month and day in ISO8601 order.

¿Why in Rails the YAML/Serialize method don't uses my date format?

Comments and changes to this ticket

  • josh

    josh July 17th, 2008 @ 02:13 AM

    • State changed from “new” to “stale”
    • Tag set to activerecord, activesupport, bug, yaml

    Closing this ticket as stale. If this is still an issue for you, feel free to reopen this ticket or create a new one with an updated description. Remember those unit tests too ;)

  • Ivan Vanderbyl

    Ivan Vanderbyl February 4th, 2009 @ 03:54 AM

    I have the same issue serialising a hash containing a Date object and can confirm that when running this in console: Date.today.to_yaml => "--- !timestamp 02/04/2009\n"

    and again in irb Date.today.to_yaml => "--- 2009-02-04\n"

    Is this something to do with Rails locals?

  • Andy Lowry

    Andy Lowry August 5th, 2009 @ 10:56 PM

    I think I know what's going on here and how to fix it. The problem is that rails redefines Date.to_s (somewhere - haven't actually found it, or perhaps didn't understand what I was looking at) so it takes an optional first argument that selects a named formatting option from those defined in:

    ActiveSupport::CoreExtensions::Date::Conversion::DATE_FORMATS
    

    If you create an entry in that table with key ":default" it will end up being used by Date.to_s when you don't supply an argument. And the YAML module, understandably (as it is independent of Rails), uses Date.to_s in this fashion. So when you add a :default date format, you actually alter the standard Date class behavior, and you will likely break YAML support for Date objects.

    You can fix this with this bit of code (and if I've got this right, something like this should make its way into the Rails codebase):

    class Date                    # reopen Date class
      def to_yaml( opts={} )      # modeled after yaml/rubytypes.rb in std library
        YAML::quick_emit( self, opts ) do |out|
          out.scalar( "tag:yaml.org,2002:timestamp", self.to_s(:db), :plain )
        end
      end
    end
    

    This uses the already-defined :db format which happens to be exactly what YAML needs (probably a bit safer to define a separate :yaml format that just happens to be identical to the :db format rather than exploiting this coincidence).

    This explains Ivan's observation, that YAMLing dates works just fine in a vanilla irb.

  • Andy Lowry

    Andy Lowry August 6th, 2009 @ 05:20 AM

    • Tag changed from activerecord, activesupport, bug, yaml to activerecord, activesupport, bug, patch, yaml

    Submitting a patch to fix this bug

  • Jason Langenauer

    Jason Langenauer September 7th, 2009 @ 05:28 AM

    I'd like to +1 this patch - I've just run into this problem as well.

  • Tom Brice

    Tom Brice April 23rd, 2010 @ 04:40 PM

    +1 to the patch. I found this ticket because the bug described here causes a model that has :serialize column to break if the column contains something with a Date object.

    I applied the patch as a monkey patch and it seem to work. Thanks Andy. I would think this could be added to 2-3-stable fairly easily

  • Austin Taylor

    Austin Taylor June 8th, 2010 @ 09:04 PM

    +1 I ran into this today.

  • Neeraj Singh

    Neeraj Singh June 25th, 2010 @ 10:23 PM

    I am not able to reproduce this problem with 2-3-stable.

    >> User.create({:changes=>{:my_date=>Date.today}})
      User Create (0.5ms)   INSERT INTO "users" ("name", "created_at", "updated_at", "changes") VALUES(NULL, '2010-06-25 21:21:37', '2010-06-25 21:21:37', '--- 
    :my_date: 2010-06-25
    ')
    => #<User id: 1, name: nil, changes: {:my_date=>Fri, 25 Jun 2010}, created_at: "2010-06-25 21:21:37", updated_at: "2010-06-25 21:21:37">
    >> u = User.first
      User Load (0.8ms)   SELECT * FROM "users" LIMIT 1
    => #<User id: 1, name: nil, changes: {:my_date=>Fri, 25 Jun 2010}, created_at: "2010-06-25 21:21:37", updated_at: "2010-06-25 21:21:37">
    >> u.changes
    => {:my_date=>Fri, 25 Jun 2010}
    
    ActiveRecord::Schema.define(:version => 20100625210553) do
    
      create_table "users", :force => true do |t|
        t.string   "name"
        t.text     "changes"
        t.datetime "created_at"
        t.datetime "updated_at"
      end
    
    end
    class User < ActiveRecord::Base
      serialize :changes
    end
    
  • Josh Partlow

    Josh Partlow August 24th, 2010 @ 10:18 PM

    • Importance changed from “” to “”

    This still seems to be an issue in Rails 2.3.8 if you select a :default format which YAML doesn't like:

    jpartlow@fookito:~/dev/glatisant/test-2.3.8$ script/console
    Loading development environment (Rails 2.3.8)
    >> d = Date.today
    => Tue, 24 Aug 2010
    >> s = d.to_yaml
    => "--- 2010-08-24\n"
    >> YAML.load(s)
    => Tue, 24 Aug 2010
    >> ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:default => '%B %d, %Y')
    => {:db=>"%Y-%m-%d", :short=>"%e %b", :number=>"%Y%m%d", :long=>"%B %e, %Y", :long_ordinal=>#<Proc:0xb755c988@/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.8/lib/active_support/core_ext/date/conversions.rb:11>, :default=>"%B %d, %Y", :rfc822=>"%e %b %Y"}
    >> s = d.to_yaml
    => "--- !timestamp August 24, 2010\n"
    >> YAML.load(s)
    ArgumentError: argument out of range
    from /usr/lib/ruby/1.8/yaml.rb:133:in `utc'
    from /usr/lib/ruby/1.8/yaml.rb:133:in `node_import'
    from /usr/lib/ruby/1.8/yaml.rb:133:in `load'
    from /usr/lib/ruby/1.8/yaml.rb:133:in `load'
    from (irb):6
    
  • csommerauer (at outfarm)

    csommerauer (at outfarm) October 13th, 2010 @ 12:09 PM

    +1 for this patch. This is still an issue in 2.3.8

  • Brian Landau

    Brian Landau November 2nd, 2010 @ 03:07 PM

    +1 for this patch, I'm still seeing this issue in 2.3.10 when using ActiveRecord to serialize a has with a date object.

  • crazyDiamond

    crazyDiamond March 24th, 2011 @ 02:39 PM

    @Andy Lowry... thank you for the Date patch. I was working on a rake task to backup and reload data and this came in very handy.

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>

Attachments

Pages