Добавить метки времени в существующую таблицу
Мне нужно добавить метки времени (created_at
& updated_at
) в существующую таблицу. Я попробовал следующий код, но он не работал.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
Ответы
Ответ 1
Помощник временной метки доступен только в блоке 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 будет обрабатывать эти столбцы как столбцы временной метки и обычно обновлять значения.
Ответ 2
Миграции - это просто два метода класса (или методы экземпляра в 3.1): up
и down
(и иногда метод change
экземпляра в 3.1). Вы хотите, чтобы ваши изменения вошли в метод 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 change_table
def change
, def change_table
и change_table
.
См. Руководство по миграции для получения дополнительной информации.
Ответ 3
Ваш оригинальный код очень близок справа, вам просто нужно использовать другое имя метода. Если вы используете Rails 3.1 или новее, вам нужно определить метод change
вместо change_table
:
class AddTimestampsToUser < ActiveRecord::Migration
def change
add_timestamps(:users)
end
end
Если вы используете более старую версию, вам нужно определить методы up
и down
вместо change_table
:
class AddTimestampsToUser < ActiveRecord::Migration
def up
add_timestamps(:users)
end
def down
remove_timestamps(:users)
end
end
Ответ 4
Ответ @user1899434 связан с тем фактом, что "существующая" таблица может означать таблицу, в которой уже есть записи, записи, которые вы, возможно, не хотите удалять. Поэтому, когда вы добавляете временные метки со значением null: false, которое является значением по умолчанию и часто желательно, все существующие записи становятся недействительными.
Но я думаю, что этот ответ можно улучшить, объединив два шага в одну миграцию, а также используя более семантический метод add_timestamps:
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
, например, если вы хотите вместо этого создавать/обновлять существующие записи на заре времени.
Ответ 5
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
Ответ 6
def change
add_timestamps :table_name
end
Ответ 7
Ник Дэвис ответ является наиболее полным с точки зрения добавления столбцов меток времени в таблицу с существующими данными. Единственным недостатком является то, что он вызовет ActiveRecord::IrreversibleMigration
при db: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
Ответ 8
не уверен, когда именно это было введено, но в rails 5.2.1 вы можете сделать это:
class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
def change
add_timestamps :my_table
end
end
для получения дополнительной информации см. " Использование метода изменения " в документации по переносу активных записей.
Ответ 9
Я сделал простую функцию, которую вы можете вызвать для добавления в таблицу каждая (при условии, что у вас есть существующая база данных) created_at и updated_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
Ответ 10
add_timestamps (table_name, options = {}) public
Добавляет столбцы меток времени (созданный_ и обновленный_кат) в имя_таблицы. Дополнительные параметры (например, null: false) пересылаются в #add_column.
class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users, null: false)
end
end
Ответ 11
Предыдущие ответы кажутся правильными, однако я столкнулся с проблемами, если в моей таблице уже есть записи.
Я получил бы "ОШИБКА: столбец created_at
содержит null
значения".
Чтобы исправить, я использовал:
def up
add_column :projects, :created_at, :datetime, default: nil, null: false
add_column :projects, :updated_at, :datetime, default: nil, null: false
end
Затем я использовал драгоценные migration_data, чтобы добавить время для текущих проектов по миграции, такие как:
def data
Project.update_all created_at: Time.now
end
Тогда все проекты, созданные после этой миграции, будут корректно обновлены. Убедитесь, что сервер тоже перезапущен, чтобы Rails ActiveRecord
начал отслеживать временные метки в записи.
Ответ 12
Здесь много ответов, но я также опубликую свой, потому что ни один из предыдущих не помог мне :)
Как уже отмечалось, #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
как NULL
, а update_at
как NULL
(пока не будет выполнено некоторое обновление строки). Новые строки будут заполнены created_at
и updated_at
как и ожидалось.
Ответ 13
Для тех, кто не использует Rails, но использует activerecord, следующее добавляет столбец к существующей модели, например, для целочисленного поля.
ActiveRecord::Schema.define do
change_table 'MYTABLE' do |table|
add_column(:mytable, :my_field_name, :integer)
end
end
Ответ 14
Это change
, а не change_table
для Rails 4.2:
class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users)
end
end
Ответ 15
Я столкнулся с той же проблемой на Rails 5, пытаясь использовать
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
Ответ 16
Я лично использовал следующее и обновил все предыдущие записи с текущим временем/датой:
add_column :<table>, :created_at, :datetime, default: Time.zone.now, null: false
add_column :<table>, :updated_at, :datetime, default: Time.zone.now, null: false