Elliot Winkler
Elliot Winkler

Reputation: 2344

Retroactively adding timestamps to a table in Rails, populating existing rows

I'd like to add timestamps to an existing table in Rails, filling in created_at and updated_at for existing rows with the current time. I know I can do this using ActiveRecord, but I'd really like to do this in a single UPDATE command, and for the life of me I can't seem to figure out a good way of doing this. Anyone have a solution they've come up with?

Upvotes: 1

Views: 952

Answers (3)

cyrusg
cyrusg

Reputation: 31

This line caused an issue with some models for me:

model.update_all(created_at: Time.now, updated_at: Time.now)

So I changed it to a less elegant one that worked:

ActiveRecord::Base.connection.execute("update #{model.table_name} set created_at = '#{Time.now}', updated_at = '#{Time.now}'")

Upvotes: 0

Elliot Winkler
Elliot Winkler

Reputation: 2344

This is the full solution I ended up going with:

class SomeMigration < ActiveRecord::Migration[5.0]
  def up
    add_and_backfill_timestamps_for(Foo)
  end

  def down
    remove_timestamps_for(Foo)
  end

  private

  def add_and_backfill_timestamps_for(model)
    add_timestamps model.table_name, null: true
    model.update_all(created_at: now, updated_at: now)
    change_column_null model.table_name, :created_at, false
    change_column_null model.table_name, :updated_at, false
  end

  def remove_timestamps_for(model)
    remove_column model.table_name, :created_at
    remove_column model.table_name, :updated_at
  end

  def now
    @_now ||= Time.zone.now
  end
end

Upvotes: 3

Joel Blum
Joel Blum

Reputation: 7878

How about

  Model.update_all(created_at: Time.now, updated_at: Time.now)

Upvotes: 2

Related Questions