Railsではマイグレーションファイルを作成してマイグレートを実行することで、テーブルが作成されます。
非常に便利で手軽にテーブルの定義・作成ができるのですが、マイグレートされた結果、どのような型が選択されるのかが隠蔽化されるという問題があると思っています。一例として、t.string
とt.text
でそれぞれカラムを定義した場合に実際にテーブルで採用される型はどうなるでしょうか。
class CreateUserTable < ActiveRecord::Migration[7.0] def change create_table :users do |t| t.string :string_name t.text :text_name t.timestamps end end end
postgresql
に接続した状態で実行すると、以下のような結果になりました。
気になるのはt.string :string_name
で定義したカラムでは型がcharacter varying(varchar)
(制限付き可変長文字列)となり、t.text :text_name
で定義したカラムではtext
(制限無し可変長文字列)が選択されるという点です。
(※ここでいう制限の有無は最大文字数のこと)
postgres=# \d users Table "public.users" Column | Type | Collation | Nullable | Default -------------+--------------------------------+-----------+----------+----------------------------------- id | bigint | | not null | nextval('users_id_seq'::regclass) string_name | character varying | | | text_name | text | | | created_at | timestamp(6) without time zone | | not null | updated_at | timestamp(6) without time zone | | not null | Indexes: "users_pkey" PRIMARY KEY, btree (id)
何が気になるのか
特定の上限を設けずに長い文字列を保存したい場合は、任意の上限を設けるよりも長さの指定が無い text もしくは character varying を使用します。
Tip: 空白でパッドされた型を使用した場合の保存領域の増加を別にして、これら 3 つの型の間でパフォーマンスに関する差異はありません
https://www.postgresql.jp/document/7.3/user/datatype-character.html
postgresql
の公式のドキュメントを見る限りはcharacter varying
型とtext
型で大きな違いはないそうですが、僕としてはcharacter varying
型を選択するのであれば最大文字数の制限はするべきだと思っています。character varying
型とtext
型の違いは最大文字数の制限が可能かどうかという点です。であれば明確に使い分けるために最大文字数の制限は行った方が役割が明確になります。
制限をしないのであれば、最初からtext
型を選択すれば良いだけの話かなと思います。
t.stringに最大文字数を制限するには
非常に簡単でマイグレーションファイルで最大文字数の指定をしてあげれば良いだけです。
class AddColumnVarcharToUser < ActiveRecord::Migration[7.0] def up add_column :users, :vchar_name, :string, limit: 50 # limitで最大文字数を50とする end def down remove_column :users, :vchar_name end end
マイグレーション後
postgres=# \d users Table "public.users" Column | Type | Collation | Nullable | Default -------------+--------------------------------+-----------+----------+----------------------------------- id | bigint | | not null | nextval('users_id_seq'::regclass) string_name | character varying | | | : vchar_name | character varying(50) | | |
先ほどとは違いcharacter varying(50)
とあるように、最大文字数の制限がされていることが分かります。
postgres=# INSERT INTO users ( created_at, updated_at, vchar_name ) VALUES ( NOW(), NOW(), /* 51文字の文字列 */ 'ああああああああああああああああああああああああああああああああああああああああああああああああああい' ); ERROR: value too long for type character varying(50)
最後に
僕は基本的にユーザーに自由な選択を与えすぎないということを意識しています。
今回の場合でいえば、t.string
にlimit: N
を指定しなければ何文字(正確には最大1GB)でもデータの登録が可能になります。例えばユーザーの名前を登録するカラムであるならば可変長に何文字も登録する必要はありません。日本人しか使わないシステムであるとすれば、どれだけ長くても50文字まで登録できれば十分でしょう。
適度に制限をするというのはテーブル設計・UXにおいても非常に重要になります。t.string
でマイグレーションを行うのであれば、必ずlimit: N
の記述もしたいところです。
少しでも「ええな〜」と思ったらイイネ!・シェア!・はてなブックマークを頂けると励みになります。