我可以在ActiveRecord中使用PostgreSQL的“特殊日期/时间输入”吗?

时间:2015-09-30 20:18:46

标签: ruby-on-rails postgresql rails-activerecord

PostgreSQL支持多个"Special Date/Time Inputs"字符串,它们在执行时会解释。例如,'now'表示“当前交易的开始时间”,'infinity'表示“晚于所有其他时间戳”。

ActiveRecord似乎不理解这些 - 例如,SomeRecord.update!(updated_at: DateTime.current)有效,但SomeRecord.update!(updated_at: 'now')尝试使用UPDATE执行NULL查询。

这些特殊字符串在Rails灯具中起作用,因为它们直接进入数据库。但有没有办法将它们与实例化模型一起使用?

2 个答案:

答案 0 :(得分:1)

您可以使用raw_write_attribute(:updated_at,'now')设置值

答案 1 :(得分:0)

使用.update_column

例如,some_record.update_column(:updated_at, 'now')

警告 - 此bypasses validations, callbacks, and normal setting of timestamps;它只是立即发出UPDATE个查询。

尽管如此,ActiveRecord撰稿人Sean Griffin said" update_column可能是最好的' hacky'回答"而像这样的特殊字符串值并没有得到很好的支持,也许不应该。 (我认为我同意 - 无论是ActiveRecord还是你自己的模型,它都会让验证变得非常尴尬。)

获得验证等的妥协

鉴于这是一个"直接到数据库"方法,避免跳过验证和回调的一种可能的妥协方案是:

ActiveRecord::Base.transaction do
  record.updated_at = Time.current         # temporary value
  record.save!                             # with validations, etc
  record.update_column(:updated_at, 'now') # final value
end

控制台的注意事项

我注意到在控制台中执行此操作时还有其他一些注意事项:

  • 事后检查记录,我看到了现在'作为created_at的值。只有在做some_record.reload后才能看到时间戳。
  • 反复这样做似乎没有给出新的时间戳。我认为这是因为现在'是"当前交易的开始时间",也许每个rails console会话使用一个交易。如果我开始使用新的控制台,我会为'现在'
  • 获得一个新值