向现有表中添加时间戳

我需要添加时间戳(created_atupdated_at)到一个现有的表。我试了下面的代码,但它不工作。

class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
112306 次浏览

时间戳助手只在 create_table块中可用。可以通过手动指定列类型来添加这些列:

class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_column :users, :created_at, :datetime, null: false
add_column :users, :updated_at, :datetime, null: false
end
end

虽然这不具有与上面指定的 add_timestamps方法相同的简洁语法,但 Rails 仍将这些列视为时间戳列,并通常更新这些值。

迁移只是两个类方法(或3.1中的实例方法) : updown(有时是3.1中的 change实例方法)。您希望您的更改进入 up方法:

class AddTimestampsToUser < ActiveRecord::Migration
def self.up # Or `def up` in 3.1
change_table :users do |t|
t.timestamps
end
end
def self.down # Or `def down` in 3.1
remove_column :users, :created_at
remove_column :users, :updated_at
end
end

如果你在3.1,那么你也可以使用 change(感谢戴夫) :

class AddTimestampsToUser < ActiveRecord::Migration
def change
change_table(:users) { |t| t.timestamps }
end
end

也许你把 def changedef change_tablechange_table搞混了。

有关更多细节,请参见 迁徙指南

class AddTimestampsToUser < ActiveRecord::Migration
def change
change_table :users do |t|
t.timestamps
end
end
end

可用的转换是

change_table :table do |t|
t.column
t.index
t.timestamps
t.change
t.change_default
t.rename
t.references
t.belongs_to
t.string
t.text
t.integer
t.float
t.decimal
t.datetime
t.timestamp
t.time
t.date
t.binary
t.boolean
t.remove
t.remove_references
t.remove_belongs_to
t.remove_index
t.remove_timestamps
end

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html

我做了一个简单的函数,你可以调用它来添加到 每个人表(假设你有一个现有的数据库)的 创建 _ at更新 _ at字段:

  # add created_at and updated_at to each table found.
def add_datetime
tables = ActiveRecord::Base.connection.tables
tables.each do |t|
ActiveRecord::Base.connection.add_timestamps t
end
end

您的原始代码非常接近正确,您只需要使用一个不同的方法名称。如果您使用 Rails 3.1或更高版本,则需要定义一个 change方法而不是 change_table:

class AddTimestampsToUser < ActiveRecord::Migration
def change
add_timestamps(:users)
end
end

如果你使用的是旧版本,你需要定义 updown方法而不是 change_table:

class AddTimestampsToUser < ActiveRecord::Migration
def up
add_timestamps(:users)
end


def down
remove_timestamps(:users)
end
end

对于那些不使用 Rails 但是使用 activerecord 的用户,下面的示例还将一列添加到现有模型中,例如整数字段。

ActiveRecord::Schema.define do
change_table 'MYTABLE' do |table|
add_column(:mytable, :my_field_name, :integer)
end
end

以前的答案似乎是正确的,但我面临的问题,如果我的表已经有条目。

我会得到‘ ERROR: column created_at include null value’。

为了解决这个问题,我使用了:

def up
add_column :projects, :created_at, :datetime, default: nil, null: false
add_column :projects, :updated_at, :datetime, default: nil, null: false
end

然后,我使用 gem Mobile _ data 迁移 _ 数据为迁移中的当前项目添加时间,例如:

def data
Project.update_all created_at: Time.now
end

然后将正确更新此迁移之后创建的所有项目。确保服务器也重新启动,以便 Rails ActiveRecord开始跟踪记录上的时间戳。

def change
add_timestamps :table_name
end

@ user1899434的响应提到了这样一个事实: 这里的“现有”表可能意味着一个已经包含记录的表,这些记录可能是您不想删除的。因此,当您添加具有 null: false 的时间戳(这是默认的,并且通常是需要的)时,那些现有的记录都是无效的。

但是我认为,通过将这两个步骤合并为一个迁移,以及使用更加语义化的 add _ time戳方法,可以改进这个问题的答案:

def change
add_timestamps :projects, default: Time.zone.now
change_column_default :projects, :created_at, nil
change_column_default :projects, :updated_at, nil
end

您可以用其他时间戳代替 DateTime.now,比如您希望在时间的黎明时创建/更新先前存在的记录。

我个人使用了以下内容,并用当前的时间/日期更新了以前的所有记录:

add_column :<table>, :created_at, :datetime, default: Time.zone.now, null: false
add_column :<table>, :updated_at, :datetime, default: Time.zone.now, null: false

它是 change,不是 Rails 4.2的 change_table:

class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users)
end
end

Add _ time 戳(table _ name,options = {}) public

将时间戳(create _ at 和 update _ at)列添加到 table _ name。

class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users, null: false)
end
end

在使用现有数据向表中添加时间戳列方面,Nick Davies 回答是最完整的。它唯一的缺点是,它将提高 ActiveRecord::IrreversibleMigrationdb:rollback

它应该这样修改,以便在两个方向上都能发挥作用:

def change
add_timestamps :campaigns, default: DateTime.now
change_column_default :campaigns, :created_at, from: DateTime.now, to: nil
change_column_default :campaigns, :updated_at, from: DateTime.now, to: nil
end

不确定这是什么时候引入的,但是在 Rails5.2.1中你可以这样做:

class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
def change
add_timestamps :my_table
end
end

有关更多信息,请参见活动记录迁移文档中的“ 使用变更方法”。

这里有很多答案,但我也会发布我的,因为之前的答案都不适合我:)

正如一些人所指出的,#add_timestamps不幸地添加了 null: false限制,这将导致旧行无效,因为它们没有填充这些值。这里的大多数答案都建议我们设置一些默认值(Time.zone.now) ,但是我不想这样做,因为这些旧数据的默认时间戳是不正确的。我不认为向表中添加不正确的数据有什么价值。

所以我的迁移很简单:

class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_column :projects, :created_at, :datetime
add_column :projects, :updated_at, :datetime
end
end

没有 null: false,没有其他限制。旧行将继续有效,created_at作为 NULLupdate_at作为 NULL(直到对该行执行某些更新)。新的行将按预期填充 created_atupdated_at

我在 Rails5上遇到了同样的问题

change_table :my_table do |t|
t.timestamps
end

我可以用以下代码手动添加时间戳列:

change_table :my_table do |t|
t.datetime :created_at, null: false, default: DateTime.now
t.datetime :updated_at, null: false, default: DateTime.now
end

这里大多数答案的问题在于,如果默认为 Time.zone.now,那么所有记录都会有运行迁移的时间作为默认时间,这可能不是您想要的。在轨道5中,你可以改用 now()。这将把现有记录的时间戳设置为运行迁移的时间,以及新插入记录的提交事务的开始时间。

< p > < code > class AddTimestampsToUsers < ActiveRecord: : 迁移 自然改变 Add _ time戳: users,default:-> {‘ now ()’} ,null: false 结束 结束

使用 Time.current是一种很好的 https://github.com/rubocop-hq/rails-style-guide#timenow风格

def change
change_table :users do |t|
t.timestamps default: Time.current
t.change_default :created_at, from: Time.current, to: nil
t.change_default :updated_at, from: Time.current, to: nil
end
end

或者

def change
add_timestamps :users, default: Time.current
change_column_default :users, :created_at, from: Time.current, to: nil
change_column_default :users, :updated_at, from: Time.current, to: nil
end

这似乎是 Rails 5.0.7中的一个干净的解决方案(发现 change _ column _ null 方法) :

def change
add_timestamps :candidate_offices, default: nil, null: true
change_column_null(:candidate_offices, :created_at, false, Time.zone.now)
change_column_null(:candidate_offices, :created_at, false, Time.zone.now)
end

这是在现有表中添加时间戳的简单方法。

class AddTimeStampToCustomFieldMeatadata < ActiveRecord::Migration
def change
add_timestamps :custom_field_metadata
end
end

我现在在 Rails 5.0上,这些选项都不管用。

唯一有效的方法是使用类型为: time戳而不是: datetime

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

在 Rails 6(可能更早)中,如果您试图将时间戳添加到一个已有的表中,并且记录已经像下面这样显示:

def change
add_timestamps :table_name
end

由于 add_timestamps默认将新列声明为 NOT NULL,因此您将得到一个错误。您可以通过添加 null: true作为参数来解决这个问题:

def change
add_timestamps :table_name, null: true
end