新人ちゃんにRailsのenumをstringで扱う方法を教えた話
三行で
この前新人研修でRailsのenumを教えました。その時にデータ型をstringで使う方法を伝えたのでその時の話
「めんどくさいからこの記事見といて」としようとしたら意外とない。せっかくなら書こうかと。
integerよりも柔軟性高いのでひとつの小技としてどうぞ
そもそもenumとは
名前を整数に割り当てるのに使われるデータ型のこと。整数に対して名前を割り当てるので、整数を直接扱うよりも人間にとって読みやすく、メンテナンス性が上がる。
データベースに保存されるときは名前ではなく、対応した整数が保存されます。
名前の通り数字を扱うことを前提としたデータ型です。
基本的な書き方
まず、enum用のカラムを追加します。
詳しい書き方とか、注意点はここでは解説しないです。
def change
add_column :models, :status, :integer, default: 0
end
該当モデルに enumを宣言する
class Model < ApplicationRecord
enum :status, [ :A, :B, :AB, :O ]
end
以上!!
こうするとconsoleでは以下のように表示されます
Model.first
#=>
id: 1,
status: "A"
read_attribute_before_type_cast
で整数を取り出すことも可能です。
Model.first.read_attribute_before_type_cast(:status)
=> 0
以下のようにすればhashで管理することもできます。
enum status: { A: 0, B: 1, AB: 2, O: 3 }
stringで書く場合
まず、データ型をstringにします。
def change
add_column :models, :status, :string, default: 'a'
end
後はhashで宣言するだけです。
class Model < ApplicationRecord
enum status: { A: 'a', B: 'b', AB: 'ab', O: 'o' }
end
コンソールで確認すると以下のようになります。
Model.first
#=>
id: 1,
status: "A"
以上!簡単!!
stringで管理することのメリットって何?
例えば今回の血液型のような決まった値で、今後変更する予定がないのであればintegerで全く問題ないと思います。
stringで管理したほうがいいパターンで行くと、値が追加される可能性があるときに使うといいと思います。
ランク管理とかで A B C で管理する予定が S が増えたとか。
そういった変化するかどうかがわからないものに対してはstringのほうが適していると思います。
だってSランクが後から追加されたらintegerの場合
enum rank: { A: 0, B: 1, C: 2, S: 3 }
ってなるんですよ!気持ち悪くないですか?(笑)
これで後からさらにDランクなんて追加された発狂しますよ(笑)
まとめ
こんな感じで小技ですがstringでenumを扱う方法を紹介させていただきました。
使うといい場面としては
決まった値で管理したいかつ、既存の値の変更はないが追加される可能性があるとき
だと思います。
時々によって変わりますが、一つの選択肢として持っておくといいかなと思いました。
それではよいエンジニアライフを(^ ^)
最後まで読んでいただきありがとうございました。
参考文献
Tech Racho ~ Railsのenumを使いこなす方法(翻訳) ~
Railsガイド~ Active Record クエリインターフェイス ~
stack overflow ~ How to store enum as string to database in rails ~