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()”
,这将始终有效。