I have a DateTime object (from DateTime.now), and an ActiveSupport::TimeWithZone object (comes from a date in the DB). I''m passing these values to the helper method distance_of_time_in_words: <%= distance_of_time_in_words(DateTime.now, @myinstance.mydate) %> In the implementation of this helper is the following: distance_in_minutes = (((to_time - from_time).abs)/60).round In production, this works as expected. In testing, this results in: ActionView::TemplateError: undefined method `abs'' for Sun Oct 26 19:49:44 UTC 1980:Time Here''s where it gets strange. I opened this up in the debugger in both environments. In test, a DateTime minus a TimeWithZone gives me a Time. Time doesn''t have an abs method, so this fails with a NoMethod exception. In production a DateTime minus a TimeWithZone results in a Rational, which does have abs! Why the different behavior in these two environments? I don''t see the DateTime minus operator being redefined by rails anywhere, but maybe I''m not looking in the right place. I''m using Rails version 2.2.2.
Actually, I was looking at the parameters in the wrong order. I need the - operator from the to_date wich is the TimeWithZone. That''s defined here: def -(other) # If we''re subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time, # otherwise move backwards #utc, for accuracy when moving across DST boundaries if other.acts_like?(:time) utc - other elsif duration_of_variable_length?(other) method_missing(:-, other) else result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other) result.in_time_zone(time_zone) end end The rails console tells me I should hit the first condition, resulting in a Time (which doesn''t support abs). I still haven''t found the magic that makes this work in production. Loading development environment (Rails 2.2.2)>> a = DateTime.now=> Sun, 05 Jul 2009 01:55:13 -0400>> a.class=> DateTime>> b = Time.zone.now=> Sun, 05 Jul 2009 05:55:31 UTC +00:00>> b.class=> ActiveSupport::TimeWithZone>> c=b-a=> Thu Jan 01 00:00:18 UTC 1970>> c.class=> Time>>On Jul 5, 1:02 am, Brian <butler.bria...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have a DateTime object (from DateTime.now), and an > ActiveSupport::TimeWithZone object (comes from a date in the DB). I''m > passing these values to the helper method distance_of_time_in_words: > > <%= distance_of_time_in_words(DateTime.now, @myinstance.mydate) %> > > In the implementation of this helper is the following: > > distance_in_minutes = (((to_time - from_time).abs)/60).round > > In production, this works as expected. In testing, this results in: > > ActionView::TemplateError: undefined method `abs'' for Sun Oct 26 > 19:49:44 UTC 1980:Time > > Here''s where it gets strange. I opened this up in the debugger in > both environments. In test, a DateTime minus a TimeWithZone gives me > a Time. Time doesn''t have an abs method, so this fails with a > NoMethod exception. In production a DateTime minus a TimeWithZone > results in a Rational, which does have abs! > > Why the different behavior in these two environments? I don''t see the > DateTime minus operator being redefined by rails anywhere, but maybe > I''m not looking in the right place. I''m using Rails version 2.2.2.
A little more information... Not all ActiveSupport::TimeWithZone instances are alike. In the definition of the minus operator (above) I consistantly see that other.acts_like?(:time) so it always returns "utc-other". The difference is, the type of utc! When the TimeWithZone is created from the DB, utc is a Date (and a Date - Date = rational). When the TimeWithZone is created from a test fixture, utc is a Time (and a Time - Date = Time). Now, at least, I understand how its possible that my subtraction is returning a different type in each case. Unfortunately for me this means the real answer is buried somewhere inside ActiceRecord code and I''m still not smart enough to proceed. :) Two questions: 1) Why isn''t anyone else hitting this? The combination of using test fixtures + calling distance_of_time_in_words can''t be THAT rare, can it? 2) Any suggestions for a workaround?
Resolved! Sometimes I''m too stubborn for my own good. Updating rails to 2.3.2 made this problem go away. The helper now works as I expect it to for both DB dates and test fixture dates. On Jul 5, 2:19 pm, Brian <butler.bria...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> A little more information... > > Not all ActiveSupport::TimeWithZone instances are alike. In the > definition of the minus operator (above) I consistantly see that > other.acts_like?(:time) so it always returns "utc-other". The > difference is, the type of utc! When the TimeWithZone is created from > the DB, utc is a Date (and a Date - Date = rational). When the > TimeWithZone is created from a test fixture, utc is a Time (and a Time > - Date = Time). > > Now, at least, I understand how its possible that my subtraction is > returning a different type in each case. Unfortunately for me this > means the real answer is buried somewhere inside ActiceRecord code and > I''m still not smart enough to proceed. :) > > Two questions: > 1) Why isn''t anyone else hitting this? The combination of using test > fixtures + calling distance_of_time_in_words can''t be THAT rare, can > it? > 2) Any suggestions for a workaround?