enum_help導入

制作中の掲示板アプリにenum_helpを導入しました。
ちゃんと定着させるためにもう一度実際に手を動かしながらやってみようと思います。

今回やりたいのは

フォームにセレクトボックスを作り選択肢を日本語で表示する

です。

Image from Gyazo
こんな感じの作ります。
i18nenumenum_helpを使って実装したいと思います。
rails newからやったので順番にいきましょう。

新規アプリ作成

rails new sample_app

名前は適当にsample_appで作成します。

cd sample_app

で移動して

rails g scaffold user name:string gender:integer

scaffoldで雛形を作り、userモデルを作成。カラムは名前と性別を作ります。
性別(gender)はinteger型にしておきます。
enum用のカラムはinteger型かboolean型かのどちらかです。
integerなら整数、booleanなら真偽値(true, false)でDBに保存されます。
選択肢が2択ならboolean、それより多い、今後増える、とかの場合はintegerがいいのかなと思います。
マイグレーションファイルを

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.integer :gender, default: 0, null: false

      t.timestamps
    end
  end
end

このように編集して

rails db:migrate

します。

gemのインストール

必要なgemをインストールしましょう。
gemfileに

gem 'rails-i18n'
gem 'enum'
gem 'enum_help'

として

bundle install

これでインストールできたかと思います。

enumの定義

userモデルでenumの定義をします。

# user.rb

enum gender: { male: 0, female: 1, secret: 2 }

i18nの設定

config/application.rbに必要な設定を記述します。

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module SampleApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    # これを追加
    config.i18n.default_locale = :ja #デフォルト言語を日本語に設定
  end
end

config/locales/ja.ymlを作成し、

ja:
  enums:
    user:
      gender:
        male: 男性
        female: 女性
        secret: 秘密

翻訳情報を作成します。

viewを整形

viewを整えます。

users/_form.html.erb

<%= form_with(model: user, local: true) do |form| %>
  <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div class="field">
    <%= form.label :gender %>
    <%= form.number_field :gender %> <%#この行を削除 %>
    <%= form.select :gender, User.genders_i18n.invert %> <%# この行を追加 %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

User.gendersでuserモデルのgenderの値をハッシュで取得します。

irb(main):001:0> User.genders
=> {"male"=>0, "female"=>1, "secret"=>2}

これをUser.genders_i18nとすると

irb(main):002:0> User.genders_i18n
=> {"male"=>"男性", "female"=>"女性", "secret"=>"秘密"}

ja.ymlファイルで設定した日本語が適用されました。
このカラム名(複数形)_i18nenum_helpで使えるようになります。
しかしこれだと
Image from Gyazo
選択肢は英語のままになっています。
ハッシュのkeyの方が取得されていますね。これに

irb(main):003:0> User.genders_i18n.invert
=> {"男性"=>"male", "女性"=>"female", "秘密"=>"secret"}

invertメソッドを付けるとkeyとvalueを入れ替えることができます。
これで再度見てみると
Image from Gyazo
日本語になりました。

最後に

無事実装できました。使用頻度が高そうな気がするのでしっかり押さえたいです。
以上となります。読んでいただきありがとうございました。