🦁

【Rails】Enumを使いこなそう

2023/04/29に公開

はじめに

Railsの実装をしていくなかで、
「セレクト式の値を管理したい」
「stetus状況を管理したい」
そんな場合などにenumが活用されると思います。
便利なenumではありますが、使い方や挙動について忘れがちなので、ここでまとめていこうと思います。

Enumとは?

結論
列挙型のことをです。

「そんなこと言われてもわからん。」
というのが大多数だと思うので、早速実例を見ていきましょう。
百聞は一見にしかず!

準備

※Userモデルが存在し、gender(性別)カラムをenumで管理している想定です

migrationの型

対象のカラムはinteger型をしようします

class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.integer :gender

      t.timestamps
    end
  end
end

定義

modelファイルにて以下のように記載して定義します

class User < ApplicationRecord
  enum gender: { male: 1, female: 2 }
end

実践

ここでは実際にどのな挙動になるか確認していきます

取得

通常

irb(main):001:0> user = User.create(gender: 1)
irb(main):002:0> user.gender
=> "male"

integer型で登録した場合は数値を返します(この場合は1)が、
enumで1=maleと定義してあるので、文字列のmaleを返します。

数値が欲しい

enumを使うと文字列が返るのがわかったと思います。
しかし、数値を返して欲しい場合もあります。(この場合だと1)
その場合は以下のようにして取得が可能です。

irb(main):001:0> user = User.create(gender: 1)
irb(main):002:0> user.gender_before_type_cast
=> 1

取得方法の方式としては以下になります。

モデル.カラム名_before_type_cast

登録

先ほどはリクエストで数値の1で作成してみました。
次にenumで定義した1に相当するmaleでリクエストしたらどうでしょうか?

irb(main):001:0> user = User.create(gender: "male")
irb(main):002:0> user.gender
=> "male"

こちらも問題なく登録から取得まで出ました。
enumで定義された値に関しては、
文字列でも登録ができるを覚えておきましょう!

こんな使い方もある

ここまででenumの基本的な機能について記載してきました。
ここから
「enumを使うとこんな使い方もできるんだ」
を紹介していきます。

値の一致確認

ユーザーが男性かどうか確認したい処理があったとします。

irb(main):001:0> user.gender == "male"
=> true

これをenumを使用すると以下のようにかけます。

irb(main):001:0> user.male?
=> true

実にシンプル!
enumに定義した値で確認ができるので
可読性がぐんと上がるのがいいところですね。

値の参照

今まで作成されたユーザーを対象に値を取得してきました。
enumではモデルから値を参照することもできます。

irb(main):001:0> User.genders[:male]
=> 1

主にマジックナンバーを防ぐために使用するといいかもです

マジックナンバーとは、
コンピュータプログラムのソースコードなどに直に記述された数値で、その意味や意図が記述した本人以外には自明ではないもの

定義名が重複した時

同じ値を定義した場合にどのよに見分ければいいのか
それを解決するのが、_prefix や _sufix になります。
実際に具体例を見てみましょう。

class User < ApplicationRecord
  enum status_A: { ok: 1, ng: 2 }, _prefix: true
  enum status_B: { ok: 1, ng: 2}, _sufix: :test
end

この場合、上記で使用したような

irb(main):001:0> user.ok?
=> error # status_Aとstatus_Bどっちを評価すればいいの??

となってしまいます。
それをさ避けるためにオプション設定を行います。
それぞれを使い方をみてみましょう。

# 前提 userのstatus_Aにはokが登録されている
# _prefix:trueの実行例
# モデル.カラム名_定義名
irb(main):001:0> user.status_A_ok?
=> true

# _suffix: :sampleの実行例
# モデル.定義名_sufixのオプション名
irb(main):001:0> user.ok_test?
=> true

日本語対応

今まで欲しい値は英語のみでしたが、
日本で対応したケースもあると思います。
その場合、gemを使うとシンプルに実現することが可能なので、
今回はgemを使用した使い方を紹介します。

i18nのデフォルト値を日本語に設定

config/application.rb
class Application < Rails::Application
+  config.i18n.default_locale = :ja # デフォルトを日本語に設定
+  config.i18n.load_path += Dir[Rails.root.join('config/locales/*.yml').to_s] #読み込みファイルを指定
end

ja.ymlファイルの作成

日本語にしたいものを記載

作成したファイルにenumで日本語にしたいものを記載する
※ymlファイルはインデントが重要なので、配置に気をつけてください

config/locales/ja.yml
ja:
  enums:
    user:
      gender:
        male: 男性
        female: 女性

確認

下準備は以上!
実際にコンソールを使って確認してみます。

# モデルから参照する場合
## モデル.カラム名(複数系)s_i18n[:定義した値]
irb(main):001:0> User.genders_i18n[:male]
=> "男性"

# DBに登録された値を参照する場合
## モデル.カラム名_i18n
irb(main):001:0> user = User.first
irb(main):002:0> user.gender_i18n
=> "男性"

このように対象の語尾にi18nをつけるだけで日本語表示が可能になります!
モデルの値を参照する場合はカラム名を複数形にする必要があるので、そこだけ注意しましょう。

まとめ

いかがだったでしょうか?
enumの基本的な使い方についてまとめてみました。
日本語表示に関してはgemを使わない方法もありますが、ロジックを組んだりする必要があるので、それは別途記事にしたいと思います。

これで以上になります!
少しでもお役に立てなら幸いです!

Discussion