0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails datetime型からdate型のマイグレーションの書き方

Posted at

「このカラムdatetimeじゃなくてdateでよさそう」

日付をあつかうからdatetimeにしてたけど、よくよく考えてみると「時間」は必要ないよねーとなったとき、dateに変換したくなりますよね。

今回のゴール

  • Bookモデルは発売日released_at(datetime)をもっている
  • マイグレーションをしてreleased_on(date)にしたい

環境

  • Rails 6.0.3
  • psql (PostgreSQL) 12.4

changeをつかったdatetime→dateの変換

def change
  rename_column :books, :released_at, :released_on
  change_column :books, :released_on, 'date USING CAST(released_on AS date)'
end

db:rollbackできますか?

これでよしよし、git commi..と、ちょっとまってください!

マイグレーションは巻き戻る(rollback)ことを考慮しておきましょう。

前述のマイグレーションをrollbackできるかを確かめてみましょう。

$ rails db:rollback

== ..... : reverting ========
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:


This migration uses change_column, which is not automatically reversible.
To make the migration reversible you can either:
1. Define #up and #down methods in place of the #change method.
2. Use the #reversible method to define reversible behavior.

なにがエラーになったのか

  • change_columnでロールバックしたとき、以前の型情報がわからないから元に戻せないから

'date USING CAST(released_on AS date)'で型を変換できたものの、**「変換前の型の情報」**が抜け落ちてしまったため、ロールバックに失敗してしまいました。

これを解決するためのひとつの方法としてup/downをつかった方法に書きかえてみましょう。

up/downをつかった方法

def up
  rename_column :books, :published_at, :release_on
  change_column :books, :release_on, 'date USING CAST(release_on AS date)'
end

def down
  rename_column :books, :release_on, :published_at
  change_column :books, :published_at, 'timestamp USING CAST(published_at AS timestamp)'
end

こうすることによって、

  • db:migrateではupdatetime -> dateが実行される
  • db:rollbackではdowndate -> datetimeが実行される

おまけ:PostgreSQLでdatetime USING CASTはエラーになる

change_column :books, :released_at, 'datetime USING CAST(released_at AS datetime)'
PG::UndefinedObject: ERROR:  type "datetime" does not exist
LINE 1: ...released_at" TYPE datetime USING CAST(published_at AS datetime)

Rails世界のdatetimeは、PostgreSQL世界ではtimestampになるという話でした :sweat_smile:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?