Rails 5.2 和 Active Record 迁移与 CURRENT_TIMESTAMP [英] Rails 5.2 and Active Record migration with CURRENT_TIMESTAMP

查看:42
本文介绍了Rails 5.2 和 Active Record 迁移与 CURRENT_TIMESTAMP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些需要具有默认值的属性.我已经设置了我的迁移以在数据库中设置默认值,如下所示:

I have some attributes that need to have default values. I've set up my migrations to set the defaults in the database as follows:

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 中构建一个新模型,一个属性会按预期工作,而另一个则不会:

The defaults work great when adding directly to the database. However, if I build a new model in Rails, one attribute works as expected, the other doesn't:

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 无效?

Is this behavior deliberate? Do I have to set the default in the model as well? Why does Post#post_type work but not Post#date_time?

推荐答案

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

ActiveRecord doesn't understand what your default value for date_time means so it doesn't give date_time a default value at all. Then, when you insert the row into the database (i.e. post.save), the database will use the current timestamp as the date_time value (presuming of course that no one has touched date_time). Rails won't know that date_time has a value after the insert so you get behavior like this:

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 以获取数据库使用的默认时间戳.

  1. Call post.reload after saving the post to get the default timestamp that the database used.

使用 after_initialize 钩子自己设置默认值:

Use an after_initialize hook to set the default yourself:

class Post < ApplicationRecord
  after_initialize if: :new_record? do
    self.date_time = Time.now
  end
end

  • 使用属性API 手动设置默认值:

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

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

    You need to use a lambda (or Proc) so that Time.now is executed at the right time.

    这篇关于Rails 5.2 和 Active Record 迁移与 CURRENT_TIMESTAMP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆