0
0

More than 3 years have passed since last update.

[Rails]Hello ~ Enum ~

Last updated at Posted at 2020-04-25

はじめに

Railsに触れ始め1ヶ月あまり、ふとenumに出会った。
その出会いについてまとめてみます

出会い

Aさん: 権限とか状態がこのサービスにはたくさんあるんだ
自分: へーそうなんですね。(覚えるの大変そうだな。。。)

しばらく一人で調べてみる。それっぽいのはあるけど、なんかよくわからん。なので聞いてみた

自分: 権限とかってどうやって判断してるんですか?
Aさん: enum 使ってる
自分: enum?何それおいしいの?

私は〜こうして〜enumと~出会ったので〜あったー。

enum is nani?

  • 皆大好きActiveRecordの追加されたモジュールです。(4.1以降)
  • 特定のカラムの値と文字列(シンボル)をマッピングさせる

何が嬉しいの?

Userモデルにstateカラムがあり、属性としてactiveinactiveがあると仮定します。おそらく下記のどちらかのパターンで設計する可能性があるかと思います。

カラム名 作成方法
state string active or inactive rails g model User state:string
state integer 1 or 2 rails g model User state:integer

この時に、「とあるユーザがactiveかどうか?」をどう実現しますか?

user.state == 'active'
user.state == 1

テーブルや属性値が少なければこれで全然問題ないと思います。ただこれが増えていくと大変です。そこで enum の出番です。

enumでやってみる

まずはUserモデルを作成します。enumで操作するカラムの型はintegerにします。
あとはmigrateしてあげましょう。

rails g model User state:integer
rails db:migrate

次に、enumでやるためにUserモデルにカラムに対するマッピングを定義します。

class User < ApplicationRecord
  enum status: { active: 1, inactive: 2 }
end

これで準備は整いました。activeなユーザを作ってみましょう。

❯ rails c
Running via Spring preloader in process 8159
Loading development environment (Rails 5.1.7)

User.create(name: 'A', state: :active)
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "users" ("name", "state", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "A"], ["state", 1], ["created_at", "2020-04-25 12:42:27.161288"], ["updated_at", "2020-04-25 12:42:27.161288"]]
   (1.0ms)  commit transaction
=> #<User id: 1, name: "A", state: "active", created_at: "2020-04-25 12:42:27", updated_at: "2020-04-25 12:42:27">

ユーザが作成されましたね。integerで型定義したはずのstateactiveと入っていますね。
さてこのユーザがactiveなユーザかどうかをチェックしてみましょう。

User.first.active?
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> true

逆にinactiveかどうかをチェックしてみましょう。

User.first.inactive?
  User Load (0.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> false

次にactiveなuser一覧を取得してみましょう。

User.where(state: :active)
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."state" = ? LIMIT ?  [["state", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "A", state: "active", created_at: "2020-04-25 12:42:27", updated_at: "2020-04-25 12:42:27">]>

上記のクエリを見ると、データベース上ではちゃんと値(integer)で保存されているのが確認できますね。enumを使うと、コードをより直感的かつわかりやすくすることができるようになります。

また定義した enum を複数形にしてあげることで定義済みのマッピングを取得することができます。

User.states
=> {"active"=>1, "inactive"=>2}

まとめ

enumを使うことでDBに保存されている値を気にする必要があまりなくなり、かつ直感的にすることができます。ぜひ活用していきたいなと思います。

素晴らしいものに出会えた。。。。。

0
0
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
0
0