ActiveRecord::Enumで定義された値のi18nをどう扱うか?


#1

いつも悩んでしまいますが、いまいちこれ!といった回答がなくて、質問します。

  • model
class Book < ApplicationRecord
  enum state: {read: 0, reading: 1}
end
  • config/locale/ja.yml
activerecord
  enum
    book
      state
       read: 読了
       reading: 読書中
  • view(form)
<%- @books.each do |book| %>
   <p><%= t book.state, 'activerecord.enum.book.state' %></p>
<% end %>
  • view(form)
<%= form_with(model: Book.new) do |form| =>
   <% = from.select :state, Book.states.keys.map{ |key| [t(key, 'activerecord.enum.book.state'), key] }
<% end %>

helperを使う、gemを使う、decoratorを使う、modelのconcernを使うなど色々方法は思い浮かびますが、
これといって綺麗にばし!っと書く方法が浮かびません。

みなさまはどう対処されていますでしょうか??


#2

enum_helpというgemを入れてるのですが、今の所特に困ったりした事はなく便利に使ってます。
simple_formも使ってるので、フォームの表示も勝手にi18n化されます。


#3

i18n使いたいがために enumerize 入れるプロジェクトもありますね。もしくは @noguchi さんが書いてるように enum_help か。

個人的にはそこまでするほどでもないか、と考えて @koheisg さんが書いているように自前で頑張ってしまうことが多いです…


#4

大筋一緒なんですが

私はこういうヘルパーを作って

 def options_for_select_from_enum(klass, target)
    enum_list = klass.send(target.to_s.pluralize.to_s)
    enum_list.map do |key, _value|
      [klass.human_attribute_name(key), key]
    end
  end

こうやって使ってます(simple_form)

= f.input :state, collection: options_for_select_from_enum(Book, :state)

ちなみにransackの検索ではこう

  def options_for_select_from_enum_number(klass, target)
    enum_list = klass.send(target.to_s.pluralize.to_s)
    enum_list.keys.map { |key| klass.human_attribute_name(key) }.zip(enum_list.values)
  end
= search_form_for @q, :builder => SimpleForm::FormBuilder do |f|
  = f.input :state_eq, collection: options_for_select_from_enum_number(Book, :state)