どうも、フリーランスエンジニアのウェブ系ウシジマくんです。Railsで開発をする際に、database.ymlにそれぞれの環境に応じた設定をしているかと思います。
かくいう私も、とあるプロジェクトでテストフレームワークであるRSpecを用いてtest環境を構築していたのですが、エンコードのエラーで少しハマってしまいました。
エラー自体は割とすぐに解消したのですが、それは英語のstackoverflowを参照したから。
同じようなエラーでハマっている方の役に立てればと思い、今回記事にすることにしました。
対象となる読者
Ruby on Railsを使ってなんらかの開発を行なっている人。
想定されるスキル感としては、ProgateとRailsチュートリアルを一通りこなした方です。
また、Railsに使用するデータベースにPostgreSQLを使用していることも前提条件となります。
エラーが出た背景
現在私が参画しているプロジェクトでは、スキルの初心者レベルの方がAWS cloud9、中級者はVagrantという開発環境です。
私自身はVagrant上にCentOS7で開発していたのですが、どうも初級者の方がcloud9で僕が作ったブランチをpullしてテスト用DBを作成しようとbin/rails db:migrate RAILS_ENV=test
を実行すると、次のようなエラーがでるみたいなんですよね。
PG::InvalidParameterValue: ERROR: new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII) HINT: Use the same encoding as in the template database, or use template0 as template. : CREATE DATABASE "celebrity_test" ENCODING = 'unicode' Couldn't create database for {"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>5, "username"=>nil, "password"=>nil, "host"=>"0.0.0.0", "database"=>"celebrity_test"} rails aborted!
エラーの内容をめちゃくちゃ意訳すると、次のような感じ。
UTF8はDBのテンプレエンコーディングのSQL_ASCIIと互換性がないから無効な値だよ。エラーを解消したかったらtemplate0を使うかこれまでのテンプレートデータベースと同じエンコーディングにしてね。
エラーを解消するには?
結論から言えば、解消するにはエラーがヒントをくれているとおり、database.ymlを次のように記述すればOKです。
test: <<: *default template: template0 encoding: utf-8 database: freelance_test
参考までにdatabase.yml全体の記述も書いておきますね。
default: &default adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: <%= ENV['USERNAME'] %> password: <%= ENV['PASSWORD'] %> host: <%= ENV['IP'] %> development: <<: *default database: freelance_development template: template0 production: <<: *default database: freelance_development username: postgres password: test: <<: *default template: template0 encoding: utf-8 database: freelance_test
なんでこのエラーが起こるの?
エラーが出た原因を調べるために、以下のサイトを参考にさせてもらいました。
rake db:create encoding error with postgresql
Set template option in your database.yml for PostgreSQL
上のサイト調べてわかったことは、database.ymlにtemplate0を指定することで、railsに対してencodingを他の影響を受けることなく、強制的にutf8にしてくれるみたいです。
これはポスグレ特有の現象っぽくて、デフォルトの状態だとtemplate0を読み込むらしいんだけど、rails newした時にOS(今回でいうとcloud9のubuntu)によっては、別で作られたtemplateを参照してDBを作成するらしい。
その時に作られたテンプレートのエンコーディングがunicordだと、明示的にtemplate0を指定しない限り、encoding: utf8と書いてもなんらかの影響で別のテンプレートのエンコーディング情報を参照しちゃいうらしいから、エラーが出るというのが原因とのことです!
ただ、実は最初にエラーが出たとき、エンコーディングをutf8だけ指定したら、一回だけうまくいったんですよね。
これについては僕の憶測でしかないんですけど、もしかしたらcloud9って文字通りクラウドで動いているから、リロードしたり再起動するたびに、システム側の読み込み先が変わっちゃうのかなーと。
ちゃんと調べたわけじゃないのでなんとも言えないですが、もしシステムに詳しい方いたら、教えてもらえたら嬉しいです!
ということで、今回のようなエラーが出た場合は、素直にtemplate: template0を記述すればOK!
ちょっとしたつぶやき
フリーランスとしてIT業界に携わるようになってから、色々なものをシビアに見れるようになりましたね。
特に時間に対しては有限であるということをかなり痛感させられます。
自分がこれまで経験してきたこととスキルの棚卸しをしながら、オリジナリティのあるプロダクトを生み出したいと思います(^^)