连接表中的时间戳列变为字符串

时间:2012-05-19 15:27:35

标签: activerecord

我有一个名为subs的表,其中有许多articlesarticles表有一个名为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 

我想从第一个查询中获取一个ActiveSupport::TimeWithZone对象。

1 个答案:

答案 0 :(得分:0)

Rails 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

Rails 4

在Rails 4中,Rails对于这种类型转换更为智能。执行SQL时,会创建ActiveRecord::Result并将column_types传递给初始化程序。在您的示例Sub.select查询中,published列将被投射为Time对象。