This project is archived and is in readonly mode.
YAML, ActiveRecord Serialize and Date formats problem
-
josh
- 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
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
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_FORMATSIf 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 endThis 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
- Tag changed from activerecord, activesupport, bug, yaml to activerecord, activesupport, bug, patch, yaml
Submitting a patch to fix this bug
-
Jason Langenauer
I'd like to +1 this patch - I've just run into this problem as well.
-
Tom Brice
+1 to the patch. I found this ticket because the bug described here causes a model that has
:serialize columnto break if thecolumncontains 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-stablefairly easily -
Austin Taylor
+1 I ran into this today.
-
Neeraj Singh
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
- 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)
+1 for this patch. This is still an issue in 2.3.8
-
Brian Landau
+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
@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.
