Rails APIドキュメント: ActiveRecord::Enum(翻訳)
enum属性を宣言します。このenum属性は、データベースのinteger型の値に対応付けられますが、以下の例のようにenum名を指定してクエリを実行できます。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ]
end
# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status # => "active"
# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status # => "archived"
# conversation.status = 1
conversation.status = "archived"
# (nilも設定可能)
conversation.status = nil
conversation.status.nil? # => true
conversation.status # => nil
enumフィールドで許可されている値に基づいたスコープも提供されます。上の例の場合、以下のスコープが利用可能です。
Conversation.active
Conversation.not_active
Conversation.archived
Conversation.not_archived
もちろん、提供されるスコープではニーズを満たせない場合は、以下のように直接クエリを実行することも可能です。
Conversation.where(status: [:active, :archived])
Conversation.where.not(status: :active)
enumのスコープ定義は、:scopes
オプションをfalse
に設定することで無効にできます。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], scopes: false
end
モデルで以下のように:default
オプションを指定することで、enum値のデフォルト値を設定できます。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], default: :active
end
conversation = Conversation.new
conversation.status # => "active"
属性とデータベースのinteger値の対応関係は、以下のようにハッシュ形式で明示的に指定できます。
class Conversation < ActiveRecord::Base
enum :status, active: 0, archived: 1
end
最後に、列挙した値を以下のようにstringカラムで永続化することも可能です。ただし、この場合はデータベースクエリが遅くなる可能性があります。
class Conversation < ActiveRecord::Base
enum :status, active: "active", archived: "archived"
end
ここで注意すべきは、enum定義で配列を使う場合、値とデータベースのinteger型の暗黙の対応付けは、配列内での出現順によって導出される点です。
上述の例では、:active
は配列の第1要素なので0
に対応付けられ、:archived
は配列の第2要素なので1
に対応付けられるといった具合です。一般に、配列のi
番目の要素はデータベースのi-1
番目の要素に対応付けられます。
すなわち、enum配列に値を追加するときは、配列内での出現順序を変えないよう注意しなければなりません。また、新しい値の追加場所は、enum配列の末尾に限定しておくべきです。
使われなくなった値を削除するときは、明示的にハッシュ構文を使う必要があります。
まれに、対応付けに直接アクセスする必要が生じることがあります。この対応付けは、以下のように属性名を複数形にしたクラスメソッド経由で公開されます。この対応付けはActiveSupport::HashWithIndifferentAccess
クラスとして返されます。
Conversation.statuses[:active] # => 0
Conversation.statuses["archived"] # => 1
enumの序数値(enum内で何番目にあるかという値)を知る必要がある場合は、このクラスメソッドを使います。たとえば、SQLクエリ文字列を手動でビルドするときに以下のような形で利用できます。
Conversation.where("status <> ?", Conversation.statuses[:archived])
複数のenumで同じ値を定義しなければならなくなった場合は、:prefix
オプションや:suffix
オプションを利用できます。:prefix
オプションにtrue
を指定すると、メソッド名にenum名がプレフィックスされ、:suffix
オプションにtrue
を指定すると、メソッド名にenum名がサフィックスされます。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], suffix: true
enum :comments_status, [ :active, :inactive ], prefix: :comments
end
上の例では、enumに関連するスコープの!
付きのメソッドや?
付きの述語メソッドに、enum名が以下のようにサフィックス(またはプレフィックス)されます。
# statusがサフィックスされる
conversation.active_status!
conversation.archived_status? # => false
# commentsがプレフィックスされる
conversation.comments_inactive!
conversation.comments_active? # => false
モデルでインスタンスメソッドが自動生成されないようにしたい場合は、:instance_methods
オプションにfalse
を指定できます。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], instance_methods: false
end
enum値を保存する前に必ずバリデーションしたい場合は、以下のように:validate
オプションを指定します。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], validate: true
end
conversation = Conversation.new
conversation.status = :unknown
conversation.valid? # => false
conversation.status = nil
conversation.valid? # => false
conversation.status = :active
conversation.valid? # => true
以下のように:validate
オプションに追加のバリデーションオプションを渡すこともできます。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], validate: { allow_nil: true }
end
conversation = Conversation.new
conversation.status = :unknown
conversation.valid? # => false
conversation.status = nil
conversation.valid? # => true
conversation.status = :active
conversation.valid? # => true
validate: { allow_nil: true }
オプションを指定しないと、以下のようにArgumentError
が発生します。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ]
end
conversation = Conversation.new
conversation.status = :unknown # 'unknown' is not a valid status (ArgumentError)
🔗 enum(name, values = nil, **options)
ソースコード: GitHub
概要
MITライセンスに基づいて翻訳・公開いたします。
参考: 17
enum
-- Active Record クエリインターフェイス - Railsガイドなお、Rails 8.0では
enum
をキーワード引数で定義する機能(Rails 7.2で非推奨化)が削除されました。参考: Remove deprecated support for defining
enum
with keyword arguments · rails/rails@b9226a6参考: Deprecate defining enums with keywords args by skipkayhil · Pull Request #50987 · rails/rails