Мне нужно добавить метки времени (created_at
& updated_at
) в существующую таблицу. Я попробовал следующий код, но он не работал.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
Мне нужно добавить метки времени (created_at
& updated_at
) в существующую таблицу. Я попробовал следующий код, но он не работал.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
Помощник временной метки доступен только в блоке 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): 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
.
См. Руководство по миграции для получения дополнительной информации.
Ваш оригинальный код очень близок справа, вам просто нужно использовать другое имя метода. Если вы используете 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
Ответ @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
, например, если вы хотите вместо этого создавать/обновлять существующие записи на заре времени.
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
def change
add_timestamps :table_name
end
Ник Дэвис ответ является наиболее полным с точки зрения добавления столбцов меток времени в таблицу с существующими данными. Единственным недостатком является то, что он вызовет 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
не уверен, когда именно это было введено, но в rails 5.2.1 вы можете сделать это:
class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
def change
add_timestamps :my_table
end
end
для получения дополнительной информации см. " Использование метода изменения " в документации по переносу активных записей.
Я сделал простую функцию, которую вы можете вызвать для добавления в таблицу каждая (при условии, что у вас есть существующая база данных) 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
add_timestamps (table_name, options = {}) public
Добавляет столбцы меток времени (созданный_ и обновленный_кат) в имя_таблицы. Дополнительные параметры (например, null: false) пересылаются в #add_column.
class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users, null: false)
end
end
Предыдущие ответы кажутся правильными, однако я столкнулся с проблемами, если в моей таблице уже есть записи.
Я получил бы "ОШИБКА: столбец 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
начал отслеживать временные метки в записи.
Здесь много ответов, но я также опубликую свой, потому что ни один из предыдущих не помог мне :)
Как уже отмечалось, #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
как и ожидалось.
Для тех, кто не использует Rails, но использует activerecord, следующее добавляет столбец к существующей модели, например, для целочисленного поля.
ActiveRecord::Schema.define do
change_table 'MYTABLE' do |table|
add_column(:mytable, :my_field_name, :integer)
end
end
Это change
, а не change_table
для Rails 4.2:
class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users)
end
end
Я столкнулся с той же проблемой на 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
Я лично использовал следующее и обновил все предыдущие записи с текущим временем/датой:
add_column :<table>, :created_at, :datetime, default: Time.zone.now, null: false
add_column :<table>, :updated_at, :datetime, default: Time.zone.now, null: false