LoginSignup
1
0

PG::DatatypeMismatch: ERROR: column "foo" cannot be cast automatically to type <barbaz> precision

Posted at

注記
この記事の投稿者は初学者であり、自身の学習の備忘録目的で記事投稿を行なっております。
情報の正確さには最大限注意をしておりますが、もし誤り等がございましたらお知らせいただけますと幸いです。

ご覧いただきありがとうございます!
Ito と申します!
Ruby on Rails初学者です。

RailsでのWebアプリを作成中、データベースにテーブルを作成した際に、設定するデータ型を間違えてしまいました。
それ自体は「あるある」だと思うのですが、migrationファイルを作成してデータ型を変更しようとした際にほんのちょびっとだけハマってしまったので備忘録として残します。

動作環境

開発環境

  • Rails 7.1.3.2
  • サーバー:localhost接続
  • データベース:PostgreSQL

エラーの詳細

エラーメッセージ

== 20240401****** ChangeLatAndLngToFloatInSpots: migrating ====================
-- change_column(:spots, :lat, :float)
bin/rails aborted!
StandardError: An error has occurred, this and all later migrations canceled: (StandardError)

PG::DatatypeMismatch: ERROR:  column "lat" cannot be cast automatically to type double precision
HINT:  You might need to specify "USING lat::double precision".
/Users ... /db/migrate/20240401******_change_lat_and_lng_to_float_in_spots.rb:3:in `change'

Caused by:
ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR:  column "lat" cannot be cast automatically to type double precision (ActiveRecord::StatementInvalid)
HINT:  You might need to specify "USING lat::double precision".

どんな時に発生したか

1.Railsジェネレータを用いて、lat(緯度)とlng(経度)属性を持つSpotモデルを作成

rails generate model Spot lat:string lng:string 

2.latカラムとlngカラムをstring型からfloat型に変更するため、Railsジェネレータを用いてマイグレーションファイルを作成する

rails generate migration ChangeLatAndLngToFloatInSpots

3.作成されたマイグレーションファイルの中身を書いていく

20240401******_change_lat_and_lng_to_float_in_spots
class ChangeLatAndLngToFloatInSpots < ActiveRecord::Migration[7.1]
  def change
    change_column :spots, :lat, :float
    change_column :spots, :lng, :float
  end
end

4.rails db:migrateを実行する
5.先ほどのエラーメッセージ

調べた結果

PostgreSQLでは、特定の型から別の型への変更を行う際に、データの解釈が自明でない場合(例えばstringからfloatへの変更など)、どのように変換するかを明示的に指定する必要があるようです。

エラーメッセージには、
latカラムをdouble precision(Railsで言うfloat型に相当する)に自動でキャスト(型変換)できないから、明示的なキャスト方法を指定する必要があるよ」 という意味が込められています。

※PostgreSQLのみ発生するのかは、不明です。

こう解決した

次のようにマイグレーションファイルを書き換えてからrails db:migrateを実行することで、無事にlatカラムとlngカラムの型をfloat型に変更することができました。

20240401******_change_lat_and_lng_to_float_in_spots
class ChangeLatAndLngToFloatInSpots < ActiveRecord::Migration[7.1]
  def up
    change_column :spots, :lat, 'float USING CAST(lat AS float)'
    change_column :spots, :lng, 'float USING CAST(lng AS float)'
  end

  def down
    change_column :spots, :lat, :string
    change_column :spots, :lng, :string
  end
end

マイグレーションファイルの中で、changeメソッドでなくupメソッドとdownメソッドを使います。(upに失敗した際に、downの内容にロールバックするため)
その際、upメソッド内のchange_columnメソッドと組み合わせてusingオプションを使用し、明示的にcastを指示しています。

up/downメソッドについては、Railsガイドをご参照ください。
3.12 up/downメソッドを使う

振り返り

Railsで開発をしている時は、型についてはほとんど考える機会がないため、複雑ではありませんが新しい体験ができたと思います✨
がしかし、もっと注意深くRailsジェネレーターにコマンドを打ち込んでいれば、こんな面倒なことにはならな買ったので、今後は実行前に見直すようにしたいと思います!

1
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
1
0