views:

170

answers:

2

By default, the datetime field from the database is being converted and stripping off the milliseconds:

some_datetime => "2009-11-11T02:19:36Z"

attribute_before_type_cast('some_datetime') => "2009-11-11 02:19:36.145"

If I try to overrride the accessor for this attribute like;

def some_datetime
  attribute_before_type_cast('some_datetime')
end

when I try "to_xml" for that model, I get the following error:

NoMethodError (undefined method `xmlschema' for "2009-11-11 02:19:36.145":String):

I have tried to parse the String to a Time object but can't get one to include the milliseconds;

  def some_datetime
    Time.parse(attribute_before_type_cast('some_datetime').sub(/\s/,"T").sub(/$/,"Z"))
  end

Can anyone help get get a datetime with milliseconds rendered by to_xml?

A: 

As it turns out, I can exclude the original datetime field, and add a custom method which in turn renders the datetime as a string to the to_xml. This feels hackish, but it's working.. Is there another way to get milliseconds directly in the original datetime field?

In each model, I exclude "except" the field names that have datetimes that I want changed, and I include "methods" with the same name returning the attribute before it is typecasted.

  def to_xml(options = {})
    options[:methods] = [:some_datetime]
    options[:except] = [:some_datetime]
    super
  end

  def some_datetime
    attribute_before_type_cast('some_datetime')
  end

Rendering to_xml is working great with models included and any other options I pass in.

revgum
A: 

I have started to learn Ruby and was impressed by Mats "Principle of Least Surprise".

But the Date and Time implementation in Ruby ( and Rails ) is full of surprises:

Starting with a plain irb:

require 'time'
=> true
dt = Time.now
=> 2010-05-31 17:18:39 +0100
Time.parse(dt.to_s) == dt
=> false !?!?!?!?
dt.to_s(:db)
ArgumentError: wrong number of arguments(1 for 0)
from (irb):5:in to_s'
from (irb):5
from C:/Ruby19/bin/irb:12:in
'

ok lets take some Rails:

sqlserver_test/development?: dt2 = Time.zone.now
=> Mon, 31 May 2010 17:24:54 CEST +02:00
sqlserver_test/development: dt2.class
=> ActiveSupport::TimeWithZone
sqlserver_test/development: Time.zone.parse(dt2.to_s) == dt2
=> false
sqlserver_test/development: dt2.to_s(:db)
=> "2010-05-31 15:24:54"
sqlserver_test/development: dt2.to_s(:iso8601)
=> "2010-05-31 17:24:54 +0200"
sqlserver_test/development: dt2.to_s(:iso8601) == dt2.iso8601
=> false

( all running on Ruby 1.9.1 with Rails 2.3.5 on Windows Xp )

Currently I only find several "hacks" regarding DateTime fields and databases but no clean solution WITHOUT surprises ...

Klaus