LoginSignup
10
3

More than 1 year has passed since last update.

Railsのenumをstringで使う方法

Last updated at Posted at 2022-06-01

新人ちゃんに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 ~

10
3
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
10
3