【问题标题】:Rails 5.2 and Active Record migration with CURRENT_TIMESTAMPRails 5.2 和带有 CURRENT_TIMESTAMP 的 Active Record 迁移
【发布时间】:2019-05-17 04:53:42
【问题描述】:

我有一些属性需要有默认值。我已将迁移设置为在数据库中设置默认值,如下所示:

class AddDefaultsToModel < ActiveRecord::Migration[5.2]
  def change
    change_column :posts, :post_type, :string, default: 'draft'
    change_column :posts, :date_time, :datetime, default: -> { 'CURRENT_TIMESTAMP' }
  end
end

直接添加到数据库时,默认值效果很好。但是,如果我在 Rails 中构建一个新模型,一个属性会按预期工作,而另一个则不会:

post = Post.new
post.post_type # draft (as expected)
post.date_time # nil (expecting the current date and time)

这种行为是故意的吗?我是否也必须在模型中设置默认值?为什么Post#post_type 有效,而Post#date_time 无效?

【问题讨论】:

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


    【解决方案1】:

    ActiveRecord 不理解 date_time 的默认值是什么意思,所以它根本不给 date_time 一个默认值。然后,当您将行插入数据库(即post.save)时,数据库将使用当前时间戳作为date_time 值(当然假设没有人接触过date_time)。 Rails 不会知道 date_time 在插入之后有一个值,所以你会得到这样的行为:

    post = Post.new
    post.date_time # `nil` because it hasn't been set at all
    # set some other values on `post`...
    post.save      # INSERT INTO posts (columns other than date_time...) values (...)
    post.date_time # `nil` even thought there is a value in the database
    post.reload    # Pull everything out of the database
    post.date_time # Now we have a timestamp
    

    你有一些选择:

    1. 保存post后调用post.reload获取数据库使用的默认时间戳。

    2. 使用after_initialize 挂钩自行设置默认值:

      class Post < ApplicationRecord
        after_initialize if: :new_record? do
          self.date_time = Time.now
        end
      end
      
    3. 使用attributes API手动设置默认值:

      class Post < ApplicationRecord
        attribute :date_time, :datetime, default: ->{ Time.now }
      end
      

      您需要使用 lambda(或 Proc),以便在正确的时间执行 Time.now

    【讨论】:

    • 我一直在使用属性 API,但如果我必须定义两次默认值,这感觉就像一个错误,所以我不得不问这个问题,以防我遗漏了什么。
    • 我认为您没有遗漏任何内容,ActiveRecord 对数据库的了解有限,因此它现在知道default current_timestampdefault now() 的含义,因此您必须自己做。如果您希望能够在不通过 Rails 的情况下插入记录,则必须执行两次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 2011-10-15
    相关资源
    最近更新 更多