web-dev-qa-db-ja.com

既存のテーブルにタイムスタンプを追加します

既存のテーブルにタイムスタンプ(created_atupdated_at)を追加する必要があります。次のコードを試しましたが、うまくいきませんでした。

class AddTimestampsToUser < ActiveRecord::Migration
    def change_table
        add_timestamps(:users)
    end
end
157
leonel

タイムスタンプヘルパーは、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はこれらの列をタイムスタンプ列として扱い、値を通常どおり更新します。

198
Ben Simpson

移行は、2つのクラスメソッド(または3.1のインスタンスメソッド):upおよびdown(および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も使用できます(Daveに感謝):

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

def changedef change_table、およびchange_tableを混同している可能性があります。

詳細については、 移行ガイド をご覧ください。

85
mu is too short

元のコードは非常に近く、別のメソッド名を使用するだけです。 Rails 3.1以降を使用している場合、change_tableの代わりにchangeメソッドを定義する必要があります。

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

古いバージョンを使用している場合は、change_tableの代わりにupおよびdownメソッドを定義する必要があります。

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

  def down
    remove_timestamps(:users)
  end
end
70
georgebrock

@ user1899434の応答は、ここにある「既存の」テーブルとは、ドロップしたくないかもしれないレコードがすでに含まれているテーブルを意味する可能性があるという事実を取り上げたものです。したがって、null:falseのタイムスタンプを追加すると、これがデフォルトであり、多くの場合望ましいのですが、これらの既存のレコードはすべて無効です。

しかし、2つのステップを1つの移行に組み合わせ、より意味のある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の代わりに他のタイムスタンプを使用できます。

40
Nick Davies
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

37
Pradeep Sanjaya
def change
  add_timestamps :table_name
end
8
Ian Vaughan

Nick Davies answer は、既存のデータを含むテーブルにタイムスタンプ列を追加するという点で最も完全です。唯一の欠点は、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
6
lightyrs

これが正確にいつ導入されたかはわかりませんが、Rails 5.2.1ではこれを行うことができます。

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

詳細については、アクティブレコード移行ドキュメントの「 change methodを使用 」を参照してください。

3
Reef Loretto

eachテーブル(既存のデータベースがある場合)に追加するために呼び出すことができる単純な関数を作成しましたcreated_atおよびpdated_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
2
Roger

add_timestamps(table_name、options = {})public

タイムスタンプ(created_atおよびupdated_at)列をtable_nameに追加します。追加オプション(null:falseなど)は#add_columnに転送されます。

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

ここにはたくさんの答えがありますが、私も投稿します。なぜなら、以前のものはどれも本当に役に立たなかったからです:)

一部の人が指摘しているように、残念ながら#add_timestampsnull: 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_atNULLとして、update_atNULLとして有効になります(行に何らかの更新が実行されるまで)。新しい行には、created_atおよびupdated_atが期待どおりに入力されます。

1
Kostis

前の答えは正しいように見えますが、テーブルにすでにエントリがある場合、問題に直面しました。

「エラー:列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

次に、gem migration_data を使用して、次のような移行に関する現在のプロジェクトの時間を追加しました。

def data
  Project.update_all created_at: Time.now
end

その後、この移行後に作成されたすべてのプロジェクトが正しく更新されます。 Rails ActiveRecordがレコードのタイムスタンプの追跡を開始するように、サーバーも再起動されていることを確認してください。

1
dbrody

Railsの場合はchange_tableではなくchangeです4.2:

class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users)
  end
end
0
Igor T.

Railsを使用せずにactiverecordを使用する場合は、次の例も既存のモデルに列を追加します。例は整数フィールドです。

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