Добавить метки времени в существующую таблицу

Мне нужно добавить метки времени (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