環境
ruby 2.5.3
Rails 5.2.4.2
enum_help (0.0.17)
rails-i18n (5.1.3)
作成法
enumの設定
class User < ApplicationRecord
validates :name, presence: true, length: { maximum: 30 }
validates :description, length: { maximum: 300 }
validates :privacy, presence: true
enum privacy: { published: 0, closed: 1 }
end
booleanにしていないのは、今後限定公開などの機能を追加することを想定しているためです。
このようにenumを設定することで、データベースで数値として扱っている値を、Railsでは文字列として擬似的に扱うことができます。
User.find_by(privacy: :published)
User Load (4.2ms) SELECT `users`.* FROM `users` WHERE `users`.`privacy` = 0 LIMIT 1
=> #<User id: 1, name: "名前", description: "詳細", privacy: "published", created_at: "2020-04-10 12:41:31", updated_at: "2020-04-10 12:41:31">
↑SQLでは`privacy` = 0
に変換されている。
また、この値は文字列でもシンボルでも指定できます。
user.privacy
=> "closed"
user.privacy = 0
=> 0
user.privacy
=> "published"
user.privacy = :closed
=> :closed
user.privacy
=> "closed"
i18nの設定
gem 'rails-i18n'
gem 'enum_help'
必要なgemを記述して、$ bundle install
でインストールします。
そして、application.rbに以下の設定を追加します。
module TestApp
class Application < Rails::Application
# 言語・タイムゾーンを日本に設定
config.i18n.default_locale = :ja
config.time_zone = 'Tokyo'
config.active_record.default_timezone = :local
# config/locales/配下の全てのrb, ymlファイルを読み込み対象とする
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
end
end
config/locales
配下に日本語化用のファイルを用意します。(ファイルの場所や名前は自由)
ja:
activerecord:
models:
user: ユーザー
attributes:
id: ID
created_at: 作成日時
updated_at: 更新日時
user:
name: 名前
description: 自己紹介
privacy: 公開設定
enums:
user:
privacy:
published: 公開
closed: 非公開
formの作成
= form_with model: @user, local: true do |f|
= f.label :name
= f.text_field :name
br
= f.label :description
= f.text_area :description
br
= f.label :privacy
= f.select :privacy, User.privacies_i18n.invert
br
= f.submit
こんな感じです。ポイントはセレクトボックスの値です。
= f.select プロパティ名, 選択肢の配列
とすればいいので、
= f.select :privacy, [['公開', 0], ['非公開', 1]]
これでも可能ですが、なんか嫌です。モデルと関連付けたい。
そこで、gemの出番です。'enum_help'
によってそれぞれ以下のようなインスタンスメソッドとクラスメソッドが使えるようになります。
user.privacy_i18n
=> "公開"
User.privacies_i18n
=> {"published"=>"公開", "closed"=>"非公開"}
これを利用して[[表示される選択肢, 渡される値], [表示される選択肢, 渡される値]]
の形の配列に置き換えます。
User.privacies_i18n.map { |k, v| [v, k] }
=> [["公開", "published"], ["非公開", "closed"]]
User.privacies_i18n.invert.to_a
=> [["公開", "published"], ["非公開", "closed"]]
どちらも同じですが、後者の方が文字数が少なくシンプルかなと思います。
(追記)
これだけ書いておいて何ですが、配列に変更する必要はありませんでした。ハッシュのままでも行けました。
ということで、User.privacies_i18n.invert
が最短です。
そして五年前の記事で既に言及していたので、ここに恥を晒しておきます。
リンク
Enums | Active Record クエリインターフェイス - Railsガイド
Rails 国際化 (i18n) API - Railsガイド