将时间戳添加到db Rails 5+中的现有表

D.K*_*K.S 8 ruby migration ruby-on-rails

尝试将Timestamps添加到现有表中.根据Api文档add_timestamps

这是我的迁移代码:

  def change
    add_timestamps(:products, null: false)
  end
Run Code Online (Sandbox Code Playgroud)

得到错误:

- add_timestamps(:products,{:null => false})rails aborted!StandardError:发生错误,此以及所有后续迁移都被取消:SQLite3 :: SQLException:无法添加具有默认值NULL的NOT NULL列:ALTER TABLE"products"ADD"created_at"datetime NOT NULL

我也试过这个帖子中的所有解决方案

同样的错误...... Rails 5.1.4 Ruby 2.4.0

spi*_*ann 25

您不能将具有非空约束的列添加到非空表,因为表中的现有行将立即具有空值,因此条件失败.

而是通过三个步骤介绍列:

def change
  # add new column but allow null values
  add_timestamps :products, null: true 

  # backfill existing record with created_at and updated_at
  # values making clear that the records are faked
  long_ago = DateTime.new(2000, 1, 1)
  Product.update_all(created_at: long_ago, updated_at: long_ago)

  # change not null constraints
  change_column_null :products, :created_at, false
  change_column_null :products, :updated_at, false
end
Run Code Online (Sandbox Code Playgroud)

  • 在迁移中使用 ActiveRecord 模型存在风险 - 例如,如果您稍后重命名“Product”,则会失败。最好用 SQL 来完成: update "UPDATE products SET create_at = NOW(), Updated_at = NOW()"` 这将始终有效。 (3认同)

Pak*_*Pak 7

我认为,在迁移过程中使用activerecord查询甚至SQL处理现有数据是错误的。

正确的5.2+ Rails方法是:

class AddTimestampsToCars < ActiveRecord::Migration[5.2]
  def change
    add_timestamps :cars, null: false, default: -> { 'NOW()' }
  end
end
Run Code Online (Sandbox Code Playgroud)

这是一个过程,因此您可以根据需要设置过去的日期。

来源:https : //github.com/rails/rails/pull/20005