おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

Rails 4.2 で postgresql を使う場合の注意事項

Rails 4.2 では、DB の string 型が255文字制限ではなくなりました。もともとあまり意味がなかったらしいです(詳しい人補足求む)。対象は postgresql と sqlite で、mysql は対象外です。

PostgreSQL, remove varchar limit. by senny · Pull Request #14579 · rails/rails

Rails 4.2 以降は、string は文字数制限未指定 の character varying 型に変換されます。ただそれって、text 型と何が違うんでしょうね。

と、調べた限りでは違いはなさそうでした。

string - PostgreSQL: Difference between text and varchar (character varying) - Stack Overflow

ちなみに Rails 4.1 で string 型のカラムに256文字以上の文字列を入れて保存するとこのようになります(PostgreSQLは 9.4.1 でためしてます)。Rails 4.2 だとエラーにならず普通に保存されます。

ActiveRecord::StatementInvalid: PG::StringDataRightTruncation: ERROR:  value too long for type character varying(255)

この挙動を頼りにして、これまで string 型に validation をかけてこなかったみなさん、ちゃんと validation かけていきましょうね(\( ⁰⊖⁰)/)

補足 character varying(n) の挙動について

上記では制限している文字数以上の文字を入れようとするとエラーと書きましたが、例外があります。超過分の文字列が空白の場合はそれが切り詰められて格納され、エラーにはならないようです。SQL標準の仕様らしいけど変な挙動ですね…。

SQL defines two primary character types: character varying(n) and character(n), where n is a positive integer. Both of these types can store strings up to n characters (not bytes) in length. An attempt to store a longer string into a column of these types will result in an error, unless the excess characters are all spaces, in which case the string will be truncated to the maximum length. (This somewhat bizarre exception is required by the SQL standard.)

PostgreSQL: Documentation: 9.4: Character Types

mysql の場合

mysql は特に挙動は変わっていません。mysql 5.6 のデフォルトである STRICT_ALL_TABLES が有効になっていると次のようなエラーになります。無効だとエラーにはならず、256文字以降が自動でカットされて格納されます

ActiveRecord::StatementInvalid: Mysql::Error: Data too long for column 'name' at row 1: INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES (?, ?, ?)