2017-05-11 10 views
-1

私は列のデータを失うことなくこのunixタイムスタンプをdatetimeフィールドに変換する方法を見つけたいので、現在列データ型が整数でデータがunixタイムスタンプとして保存されています。 Railsの移行で列を整数から日時に変更する方法はありますか?

class ChangeRecordTimeToDatetime < ActiveRecord::Migration 
    def up 
    as = Audio.all.map {|a| {id: a.id, record_time: Time.at(a.record_time)}} 
    Audio.all.update_all("record_time = NULL") 
    change_column :audios, :record_time, :datetime 
    as.map {|a| Audio.find(a[:id]).update(record_time: a[:record_time])} 
    end 

    def down 
    as = Audio.all.map {|a| {id: a.id, record_time: a.record_time.to_i}} 
    Audio.all.update_all("record_time = NULL") 
    change_column :audios, :record_time, :integer 
    as.map {|a| Audio.find(a[:id]).update(record_time: a[:record_time])} 
    end 
end 
を、これは私に事前にこの

Mysql2::Error: Incorrect datetime value: '1493178889' for column 'record_time' at row 1: ALTER TABLE `audios` CHANGE `record_time` `record_time` datetime DEFAULT NULL 

おかげのようなエラーがスローされます:今、次のように私は、移行ファイルを作成しました。

+1

UNIXタイムスタンプを挿入する前に、UNIXタイムスタンプをDateTimeオブジェクトに変換する必要があります。 'DateTime.strptime(" 1493178889 "、 '%s')' –

+0

ありがとう、現在私は 'Time.at(1493178889)'を使っていますが、 'DateTime.strptime(" 1493178889 "、 '%s')'と 'Time.at(1493178889)'を使ってください。 –

+1

'DateTime.strptime'は' DateTime'オブジェクトを返します。 'Time.at'は' Time'を返します。あなたの列は 'DATETIME'なので、可能であればRubyの' DateTime'を使いたいと思うでしょう。 –

答えて

1

UNIXタイムスタンプを挿入する前に、そのタイムスタンプをDateTimeオブジェクトに変換する必要があります。これでできるのはDateTime.strptime(<timestamp>,'%s')です。

def up 
    as = Audio.all.map {|a| {id: a.id, record_time: DateTime.strptime(a.record_time.to_s, '%s')}} 
    remove_column :audios, :record_time 
    add_column :audios, :record_time, :datetime 
    as.map {|a| Audio.find(a[:id]).update(record_time: a[:record_time])} 
    end 
+0

これは私に同じエラーを投げます。 –

3

私はこの種のもののために完全にはActiveRecordをスキップしたいし、データベース内ですべての操作を行います。

だからあなたの質問にこれを適用するには、これを試してみてください。列の型を変更しながら古い値を新しい値に変換する方法を指定するデータベースもありますが、MySQLでそれを行う方法はわかりません。代わりに、手で行うことができます。

  1. 新しいデータ型の新しい列を追加します。
  2. 日付の型を変換する際に、古い値を新しい列にコピーする単一のUPDATEを実行します。これにはMySQLのfrom_unixtimeを使用できます。
  3. 元の列を削除します。
  4. 新しい列の名前を古い名前に変更します。
  5. 元の列にあったインデックスを再構築します。

移行にそれを翻訳:あなたはここにデータベース固有のコードの中にもいる

def up 
    connection.execute(%q{ 
    alter table audios 
    add record_time_tmp datetime 
    }) 
    connection.execute(%q{ 
    update audios 
    set record_time_tmp = from_unixtime(record_time) 
    }) 
    connection.execute(%q{ 
    alter table audios 
    drop column record_time 
    }) 
    connection.execute(%q{ 
    alter table audios 
    change record_time_tmp record_time datetime 
    }) 
    # Add indexes and what not... 
end 

ので、ストレートSQLと一緒に行くことは私には合理的であると思われます。もちろん、change_columnupdate_allコール(おそらくreset_column_informationコールでモデルクラスを更新する)に変換することはできますが、その点は表示されません。カラムタイプの変更には、ほとんど常にデータベース固有のコードが必要です)と移行は、とにかく一時的な橋渡しを意図しています。

関連する問題