Railsでi18n対応したenumを使うならenumerizeがオススメ[RubyGem]


2/15に ハレノヒ さんで開催された「Sendagaya.rb #137」に参加ました。その中でRailsの enum と『brainspec/enumerize - GitHub』を使ったほうがいいかという話が参考になったのでメモです。


🐠 Railsのenum

Railsのenumの特徴だが機能がシンプル(既存のメソッドとのバッティング等)なのと、i18nに対応していない。
zmbacker/enum_help - GitHub』を使うことでi18n対応は可能。

あとは @fukajun さんが最近ハマった事例。

- enumはvalueに Integer型を取ることもできるし、String型を取ることもできる
- enumにStringを使うと、DBの値が何かが一目でわかるようになる。だが、DBの容量増やIndex更新の負荷がある
- enumにIntegerを使うと、DBの容量減やIndex更新の高速化等に貢献。だが、ちょっと運用負荷がある
- rails_adminではenumのvalueをInteger前提にしている実装がある。使ってるとハマる

悩ましいところですが、enum は素直にIntegerを使ったほうが良さそう。

🎳 RubyGemsのenumerizeについて

Active Recordで18n対応したenumを作るのに便利なのがRubyGem『brainspec/enumerize - GitHub』。

それ以外にも便利な機能がいくつか実装されている。まずはベーシックなi18n対応から。

# Migration
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :sex
t.string :role
t.timestamps
end
end
end
# Model:
class User < ActiveRecord::Base
extend Enumerize
enumerize :sex, in: { mail: 1, female: 2}
end
# I18n:
en:
enumerize:
user:
sex:
male: "Male"
female: "Female"

スコープ的な使い方をすることもできます。

class User < ActiveRecord::Base
extend Enumerize
enumerize :sex, :in => [:male, :female], scope: true
enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status
end
User.with_sex(:female)
# SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female')
User.without_sex(:male)
# SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male')
User.having_status(:blocked).with_sex(:male, :female)
# SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female')

formとかにも簡単に使えます。

<%= form_for @user do |f| %>
<%= f.select :sex, User.sex.options %>
<% end %>

共通的に値を扱うクラスを作ることもできる。

module PersonEnumerations
extend Enumerize
enumerize :sex, in: %w[male female]
end
class Person
include PersonEnumerations
end
class User
include PersonEnumerations
end

SimpleFormやRSpecの対応も充実しており、実際に使いやすさが追求されているのが好感を持てます。
個人的には、Railsのenumの機能だけでこと足りる場合はそちらを使い、enumerizeは便利な機能やi18n対応したい場合に使うようにしたいと思います!

brainspec/enumerize - GitHub

👽 あとがき

懇親会で六本木の英国発ブリュードッグ(BrewDog)にいきました。珍しいビールの話を聞けておもしろかった! 次回も楽しみ!

📚 おすすめの書籍