1

I have a table named subs which has many articles. The articles table has a timestamp column called published.

Sub.select( "subs.*,MAX(articles.published) published").joins("LEFT OUTER JOIN articles ON subs.id=articles.sub_id").group("subs.id").first.published.class
=> String
Article.select("max(published) published").group("id").first.published.class
=>  ActiveSupport::TimeWithZone 

I want to get an ActiveSupport::TimeWithZone object back from the first query.

4

1 回答 1

0

导轨 3

Rails 根据其数据库列定义确定如何键入转换属性。例如,假设您的模型created_at上有一个方法。Sub加载记录时read_attribute使用(ActiveRecord::AttributeMethods::Read)。这用于type_cast_attribute确定如何根据列信息转换值。例如,如果您使用的是 PostgreSQL,它可能会使用:

Sub.columns.detect { |c| c.name == "created_at" }.type_cast_code("v")
=> "ActiveRecord::ConnectionAdapters::PostgreSQLColumn.string_to_time(v)"

但是 Rails 不知道如何处理Sub模型上没有的列。所以它只返回一个String. 如果您需要使用ActiveSupport::TimeWithZone对象,可以使用以下方式转换值:

published = Sub.select( "subs.*,MAX(articles.published) published").joins("LEFT OUTER JOIN articles ON subs.id=articles.sub_id").group("subs.id").first.published
published.present? ? Time.zone.parse(published) : nil

导轨 4

在 Rails 4 中,Rails 对这种类型转换更加智能。当 SQL 被执行时,ActiveRecord::Result被创建并且column_types被传递给初始化器。在您的示例Sub.select查询中,该published列将被转换为一个Time对象。

于 2015-05-07T01:58:59.863 回答