Ruby on rails 将时间戳添加到db Rails 5+;

Ruby on rails 将时间戳添加到db Rails 5+;,ruby-on-rails,ruby,migration,Ruby On Rails,Ruby,Migration,正在尝试向现有表添加时间戳。 据 以下是我在迁移中的代码: def change add_timestamps(:products, null: false) end 获取错误: *-- add_timestamps(:products, {:null=>false}) rails aborted! StandardError: An error has occurred, this and all later migrations canceled: SQLite3::

正在尝试向现有表添加时间戳。 据

以下是我在迁移中的代码:

  def change
    add_timestamps(:products, null: false)
  end
获取错误:

*-- add_timestamps(:products, {:null=>false})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL: ALTER TABLE "products" ADD "created_at" datetime NOT NULL*
我也尝试过这方面的所有解决方案

同样的错误。。。 轨道5.1.4
Ruby 2.4.0

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

相反,请分三步介绍这些列:

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

  # backfill existing records with created_at and updated_at
  # values that make 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 to not null constraints
  change_column_null :products, :created_at, false
  change_column_null :products, :updated_at, false
end

我喜欢@spickermann的方法,因为它考虑了现有记录,并且可能您的迁移已经一直到生产阶段,他的方法确保了数据的持久性

尽管如此,你们中的许多人可能会发现自己处于这种情况,但仍处于开发阶段,这意味着没有真正的敏感数据,你们可能会害怕丢失。。。这使您在如何执行表中的更改方面有了更多的自由

如果代码和记录仅在本地存在(如果仍然没有创建记录,请跳过步骤1),并且该表是在上次迁移中创建的,我的建议是:

1.-删除该表中的所有记录

2.-转到迁移文件,通过添加
t.timestamps
对其进行编辑,使其看起来像这样:

    class CreateInstitutionalLegals < ActiveRecord::Migration[5.0]
      def change
        create_table :institutional_legals do |t|
          # Your original migration content goes here
          .
          .
          t.timestamps # This is your addition
        end
      end
    end
class CreateInstitutionalLegals
3.-然后转到控制台并输入
rails:db:redo
。如前所述,该命令是执行回滚然后再次迁移回的快捷方式

现在,您将看到您的模式在
和列中使用相应的
created\u和
updated\u进行更新


这样做的具体好处是非常容易做到,您不需要创建额外的迁移文件,并且可以学习使用非常方便的命令;)

在我看来,在迁移中使用activerecord查询甚至SQL操作现有数据是错误的

正确的rails 5.2+方法是:

class AddTimestampsToCars < ActiveRecord::Migration[5.2]
  def change
    add_timestamps :cars, null: false, default: -> { 'NOW()' }
  end
end
class-AddTimestampsToCars{'NOW()'}
结束
结束
这是一个过程,所以如果你愿意,你应该能够在过去设定一个日期


来源:

我使用的是rails 5.0,这些选项都不起作用。
rails:db:redo
可以工作,但对大多数人来说不是一个可行的解决方案

唯一有效的是

def change
    add_column :products, :created_at, :timestamp
    add_column :products, :updated_at, :timestamp
end

我也有同样的问题。我希望最终结果严格等同于新数据库上的
add\u timestamps:products

我没有运行要回填的查询,而是执行了一个三步流程

  • 将允许为空且默认为当前回填时间的列添加到当前回填时间
  • 将约束更改为NOTNULL
  • 删除默认值
它是可逆的

    add_column :products, :created_at, :datetime, precision: 6, null: true, default: -> { "CURRENT_TIMESTAMP" }
    add_column :products, :updated_at, :datetime, precision: 6, null: true, default: -> { "CURRENT_TIMESTAMP" }

    change_column_null :products, :created_at, false
    change_column_null :products, :updated_at, false

    change_column_default :products, :created_at, from:  -> { "CURRENT_TIMESTAMP" }, to: nil
    change_column_default :products, :updated_at, from:  -> { "CURRENT_TIMESTAMP" }, to: nil

注意:这是Rails 6.1和PostgreSQL的做法,实际上,您可以在不传递
选项的情况下添加列,这就是Rails 5中
添加时间戳的做法,
null:false
是默认值。如果我错了,请纠正我。我也尝试过不传递选项,但在迁移中使用ActiveRecord模型时遇到了相同的错误风险——例如,如果您稍后重命名
产品
,这将失败。最好只使用SQL:
update“updateproducts SET created_at=NOW(),updated_at=NOW()”
,这将始终有效。