LoginSignup
43
55

More than 5 years have passed since last update.

【Rails】enum カラム用 select Form Helper を実装

Last updated at Posted at 2017-06-15

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 を適用して整数値を格納する.

初期状態のフォームは下図の通り.

image.png

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>

image.png

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 が日本語化できる.

image.png

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>

gem/サンプル

43
55
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
55