Railsにおけるenum
「Enum」は「列挙型」のこと。 この列挙型を扱う機能としてRuby on Rails4.1からActiveRecord :: Enumと言うモジュールが追加となった。
この機能は、モデルの数値カラムに対して文字列による名前定義が可能。また、データ操作用の便利なメソッドも提供してくれる。enumは主に以下の時に、使われる。
- 頻繁に更新が発生する
- 名前定義が中規模〜大規模
- 複数モデルで利用されている
モデルの中で、has_manyやvalidatesがあるところに設置。基本的な定義は以下の通り。
enum public_flag: {unpublished: 0, published: 1}
これで定義したモデルのオブジェクトに「unpublished」「published」というメソッド、そのインスタンスについて「unpublished!」「published!」「unpublished?」「published?」というメソッドが使えるようになる。どうなるかというと・・・
Article.published =>公開された記事がすべて返される。 Article.unpublished =>非公開記事がすべて返される。 @article = Article.find(1) @article.published? => true # この記事が公開されているのでtrueが返る。 @article.unpublished? => false #記事を非公開にする。「!」をつけることで更新される。 @article.unpublished! @article.unpublished? => true # 非公開に変えられたので、falseになる。 @article.published? => false
prefix(接頭辞)suffix(接尾辞)を使う
class Event < ActiveRecord::Base enum status: [:active, :inactive, :free], _prefix: true enum payment_type: [:cash, :credit_card, :free], _prefix: true end
_prefix: true
各 enum 行の後ろに prefix: true を付与。 :free は、 enum status と enum payment_type のどちらにも存在する値だが、 prefix を付与することで重複エラーにはならない。結果、次のようになる。
# 頭に status_ を付与 > event.status_inactive! # 更新(UPDATE) > event.status_inactive? # true > event.status_active? # false # 頭に payment_type_ を付与 > event.payment_type_free! # 更新(UPDATE) > event.payment_type_free? # true > event.payment_type_cash? # false > event.payment_type_credit_card? # false # 接頭辞なしはエラーになる。注意!! > event.active? Traceback (most recent call last): 1: from (irb):11 NoMethodError (undefined method `active?' for #<Conversation:0x00007ff78097c910>) # オブジェクトにも適用できる Event.payment_type_free => 支払いタイプがfreeのイベントが全て返る。
_suffix: true
接尾辞。以下の通り。
class Conversation < ActiveRecord::Base enum status: [:active, :archived], _suffix: true enum comments_status: [:active, :inactive], _suffix: true end
で、どうなるかと言うと・・・
# お尻に _status を付与 > conversation.archived_status! # 更新(UPDATE) > conversation.archived_status? # true > conversation.active_status? # false # お尻に _comments_status を付与 > conversation.active_comments_status! # 更新(UPDATE) > conversation.active_comments_status? # true > conversation.inactive_comments_status? # false # 接尾辞なしはエラーになる > conversation.active? Traceback (most recent call last): 1: from (irb):11 NoMethodError (undefined method `active?' for #<Conversation:0x00007ff78097c910>)