0

I have send json response of a Rails AREL query result based on two tables. The response includes two timestamp columns: updated_at and updated_at_table_2. I override ActiveSupport::TimeWithZone.as_json method to obtain the desired datetime format for JSON. The same approach is shown at

http://stackoverflow.com/questions/2937740/rails-dates-with-json

My current JSON response is: { "updated_at":"10/26/2012 22:04:07 -0400", "updated_at_table_2":"2012-10-27 02:04:07.463015" }

I want them to be the same. I relies below Rails code to produce json.

render :json => { :customer_order  =>  @customer_order  }

where @custoemr_order derived from:

CustomerOrder.select(%Q[
      updated_at,
      c.updated_at as updated_at_table_2
    ] ).
    joins( %{ as co inner join customers as c on (co.customer_id = c.id)

Question: how can I tell Rails 3 to process as_json the same way for updated_at_table_2 as for updated_at column?

Any suggestions/pointers are great too.

Note: I found this post asking about the same root problem (though not about json) without good solution. :

http://stackoverflow.com/questions/12067173/rails-postgres-not-returning-timezone-info-on-column-from-joined-table
GeorgeW
  • 566
  • 5
  • 17
  • Why not let the server work in UTC exclusively, send ISO 8601 timestamp strings to the clients, and let the clients apply whatever timezone adjustments are needed? – mu is too short Oct 27 '12 at 04:41
  • @muistooshort Agreed! I wished I could use Rails default format as in "2012-10-27 02:04:07.463015" at browser client side. However, Safari won't accept it in a Date object, which I will need to process at browser client (though chrome works fine). I think it is easier to format timestamp string properly on server side. – GeorgeW Oct 27 '12 at 17:41

1 Answers1

1

If you look at what your query gives you, you'll see exactly where you're going wrong:

 > o = CustomerOrder.select(%Q[ ... ]).joins(...)
 > puts o.updated_at.class
=> ActiveSupport::TimeWithZone
 > puts o.updated_at_table_2.class
=> String

ActiveRecord has no way of know what sort of thing updated_at_table_2 is supposed to be so it leaves it as a String and your to_json monkey patch won't be applied to strings.

If you want to keep using your to_json monkey patch (which I think is a bad idea), then you need to manually convert updated_at_table_2 to an ActiveSupport::TimeWithZone with something like this:

x = ActiveSupport::TimeWithZone.new(
    Time.parse(o.updated_at_table_2),
    Time.zone
)
# x is now an ActiveSupport::TimeWithZone

Alternatively, you could load the associated object and call updated_at on that.

I'd scrap the whole approach though: let the server work exclusively in UTC, send the clients timestamps in an ISO-8601 format, and let the clients deal with applying the local timezone.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • Is there a way to tell Rails to convert Timestamp columns to String in a consistent format? Regardless the timestamp columns are from joined table or not. – GeorgeW Oct 27 '12 at 17:43
  • I do plan to use UTC, but want to use a consistent datetime string that I can pass to a javascript Date object after appending ' -0000' to it. However Safari is giving me problems. I have a lot of JSON result to send back to client side via AREL query over joins of multiple tables. That is why I look for a simple config change or overriding some as_json method once for all. – GeorgeW Oct 27 '12 at 17:51
  • The problem is that Rails doesn't know you have a timestamp, it just sees a string. The first one is a column in your model so Rails knows what it is. I'd still go with ISO 8601 formats and add some parsing JavaScript in the client, pulling apart ISO 8601 by hand is trivial. – mu is too short Oct 27 '12 at 18:25
  • Thanks for your help, I accept your answer and turn my focus on javascript. – GeorgeW Oct 27 '12 at 19:06