rails/rails — pull request #8134 by alexdowad (2012-11-06 21:46:40+00:00)
Title: Make YAML.dump work with ActiveSupport::TimeWithZone (under both Ruby 1.8/1.9)

Just ran into this one while working on a legacy Rails 2.3 site.

Try `YAML.load(YAML.dump(t))` where `t` is an instance of `ActiveSupport::TimeWithZone`. Under Ruby 1.9.3, this fails with the following message:

NoMethodError: undefined method `period_for_utc' for nil:NilClass
from /home/alex/Programming/Ruby/rails/activesupport/lib/active_support/time_with_zone.rb:58:in `period'
from /home/alex/Programming/Ruby/rails/activesupport/lib/active_support/time_with_zone.rb:44:in `time'
from /home/alex/Programming/Ruby/rails/activesupport/lib/active_support/time_with_zone.rb:304:in `respond_to?'
from /home/alex/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:284:in `init_with'

The solution is to backport `TimeWithZone#encode_with` from Rails 3.

Under Ruby 1.8.7, `YAML.dump` also fails, with a different message:

NoMethodError: private method `gsub' called for #
from ./activesupport/lib/active_support/time_with_zone.rb:145:in `to_yaml'

Under Syck, `YAML.dump` passes a `StringIO` to `to_yaml` (rather than the "options" Hash which the author of `TimeWithZone#to_yaml` seemed to expect). Naturally, `gsub` fails on the `StringIO` object. The solution is simply to convert it to a String first.