model で enum を指定したカラムを form select で扱いやすくする Form Helper を実装した.
追記
gemにしました ⇢ enum_select_rails
前提
- Rails 5.0.3
- Ruby 2.4.0
User 作成
$ bundle exec rails g scaffold User name:string gender:integer
gender カラムは enum を適用して整数値を格納する.
初期状態のフォームは下図の通り.
enum を定義
app/models/user.rb
class User < ApplicationRecord
enum gender: {
female: 0,
male: 1,
unanswered: 2
}
end
enum に合わせてフォームを変更
model に enum を定義すると,下記のように enum の一覧が取得できる.
number_field
ではなく select
に変更する.
app/views/users/_form.html.erb
<!-- 初期状態 -->
<div class="field">
<%= f.label :gender %>
<%= f.number_field :gender %>
</div>
<!-- 下記に変更 -->
<div class="field">
<%= f.label :gender %>
<%= f.select :gender, User.genders.keys.map {|k| [k, k]} %>
</div>
i18n対応
enum_help をインストール
この gem を用いて i18n の日本語文字列を扱いやすくする.
Gemfile
gem 'enum_help'
設定追加
application.rb を更新し,自作した locales が読み込まれるようにする.
config/application.rb
# i18n
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
config.i18n.default_locale = :ja
config.i18n.available_locales = [:ja, :en]
locale作成
locale ファイルを作成する.
User.genders_i18n
のように サフィックスに _i18n
をつけることで下記のように定義した値が取得できるようになる.
config/locales/models/user/ja.yml
ja:
activerecord:
models:
user: ユーザー
attributes:
user:
name: 氏名
gender: 性別
enums:
user:
gender:
female: 女性
male: 男性
unanswered: 未回答
フォーム更新
app/views/users/_form.html.erb
<!-- 下記に変更 -->
<div class="field">
<%= f.label :gender %>
<%= f.select :gender, User.genders_i18n.keys.map {|k| [User.genders_i18n[k], k]} %>
</div>
このように Select が日本語化できる.
Form Helper を拡張
毎回書くのは冗長なので共通化する.
config/initializer/extensions/form_helper_extension.rb
class ActionView::Helpers::FormBuilder
def enum_select(record, options = {}, html_options = {})
pluralized = record.to_s.pluralize
klass = self.object.class
base = klass.send(pluralized)
i18n = klass.send("#{pluralized}_i18n")
select record.to_sym, base.keys.map { |k| [i18n[k], k] }, options, html_options
end
end
enum_select
を適用.
app/views/users/_form.html.erb
<div class="field">
<%= f.label :gender %>
<%= f.enum_select :gender %>
</div>