🎲
【Rails】gem Enumerize で enum を扱う
はじめに
gem Enumerize を使って enum を扱う機会がちょこちょこあったので、
書き方について少しまとめたいと思います。
Enumerize
この記事に書いてあることのほとんどはここに書いてあります🤭
Enumerize を使った書き方
私が遭遇したケースと書き方をあげていきます。
基本
class User
extend Enumerize
enumerize :role, in: [:user, :admin]
end
このように、モデルに定義することで enum として扱うことができます。
カスタム値で属性の値を保存したい
:in
オプションでハッシュを渡すことで
カスタム値(integer等)を使って列挙型の属性値を保存することが可能。
class User < ActiveRecord::Base
extend Enumerize
enumerize :role, in: {:user => 1, :admin => 2}
end
user = User.new
user.role = :user
user.role #=> 'user'
user.role_value #=> 1
User.role.find_value(:user).value #=> 1
User.role.find_value(:admin).value #=> 2
attribute_value
とすることで定義した値が取得できます。
テキスト値の配列を取得したい
User.status.values
=> ['student', 'employed', 'retired']
テキスト値からキーの配列を取得したい
User.status.values
=> ['student', 'employed', 'retired']
i18n 対応
class Person
extend Enumerize
extend ActiveModel::Naming # plain Ruby オブジェクトで I18n を使用したい場合
enumerize :status, in: %w[student employed retired], i18n_scope: "status"
end
# localization file
en:
status:
student: "Student"
employed: "Employed"
retired: "Retiree"
i18n に対応した属性値
@user.status = :student
@user.status_text # => 'Student'
属性値の配列
User.status.values # => ['student', 'employed', 'retired']
i18n に対応した属性値の配列
User.status.values.collect(&:text) # => ['Student', 'Employed', 'Retiree']
値ごとに集計したい
class Customer < ActiveRecord::Base
extend Enumerize
enumerize :sex, :in => [:male, :female], scope: true
end
customer_counts = Customer.group(:sex).count # => {"male"=>23, "female"=>15}
customer_counts["male"] # => 23
customer_counts["female"] # => 15
Enum 値を共通化したい
同じ属性を複数箇所で使いたい場合は、
Module 化して、各class で include する。
module StatusEnumerations
extend Enumerize
enumerize :status, in: [:new, :doing, :done]
end
class Hoge
include StatusEnumerations
end
class Fuga
include StatusEnumerations
end
私の場合は、
同じ属性の値を他のクラスで使いたい
かつ
日本語のテキストから値を更新したい
というケースだったため
モジュールにメソッドを定義して共通化することにしました。
(以下はあくまでわかりやすくしたものです)
module StatusEnumerations
extend Enumerize
enumerize :status, in: [:new, :doing, :done]
def convert_status_value(value)
status = {
'新規' => 'new',
'着手中' => 'doing',
'完了' => 'done'
}
status[value]
end
end
おわりに
直近で遭遇した Enumerize を使った書き方についてまとめてみました。
まだまだできることはたくさんあるので、気になる人は調べてみてください。
Discussion