rails4.1からActiveRecord::Enum
が採用されて、困ったことになった。
Typusの標準でつけていた、セレクトボックスの機能に対しては、モデルにstatuses
の様に、カラム名の複数形で選択肢の名前を記述させる仕様が、ActiveRecord::Enum
の仕様と被ってしまった。
どうやって、この問題をなるべく綺麗に回避しようかと考えた結果の自分なりのログです。
enum_help
を導入する
他のgemだと、rails admin、active adminそれぞれで、カラム名にひと単語加えたエイリアスを貼ったりする方法で管理をしていた。
そもそも、railsが標準でenumを導入したのに、そのi18nの方法は全く手をつけないでしまったのが、railsコミュニティ死ね!と言いたくなる片手落ちの解決方法なのですが、現実策としては、i18nを拡張するgemを採用して、それに合わせてtypusをカスタマイズしてしまう方法でした。
簡単に検索した結果、enum_helpの評判が良さそうなのでそのまま採用してカスタマイズした結果、案外よく動いてしまったので、反芻することなくそのまま使ってしまっています。
まずは、gemfileに記述を行なって、bundle install
。
gem "enum_help"
これで、カラム名にi18nを付ければi18nが行われる様になりました。
class User < ActiveRecord::Base
enum status: { retired: 0, entried: 1 }
end
User.statuses_i18n # {"retired"=>"退会済", "entried"=>"入会中"}
user.status_i18n # 入会中
あとは、i18nに対応しているメソッドがあるときはそれを実行する様に、typusの内側を書き換えてあげるだけです。
以下のコードをapp/helpers/admin/resources/data_types/selector_helper.rb
というテキストファイルに貼り付けてください。typusの既存の機能を上書きして、先に_i18n
が付いているメソッドを探して実行する様になります。
module Admin::Resources::DataTypes::SelectorHelper
def table_selector_field(attribute, item)
item.try("#{attribute.to_s}_i18n") || item.mapping(attribute)
end
def display_selector(item, attribute)
item.try("#{attribute.to_s}_i18n") || item.mapping(attribute)
end
end
同じ様に編集画面で作成するセレクトボックスも、以下のコードを作成して、_i18n
の付いたメソッドを先に探す様に、既存の機能を上書きしてしまいます。
<%
custom = { :rows => @resource.typus_options_for(:form_rows) }
options = options.merge!(custom)
%>
<div class="control-group" id="<%= attribute_id %>">
<%= form.label attribute, label_text, { :class => "control-label" } %>
<div class="controls">
<% if attribute=="role" and admin_user.role!="admin" %>
<% html_options.merge!(disabled: true) %>
<%= form.select attribute, @resource.send(attribute.pluralize), options, html_options %>
<% else %>
<%= form.select attribute, @resource.try("#{attribute.pluralize}_i18n").try(:invert) || @resource.send(attribute.pluralize), options, html_options %> <% end %>
</div>
</div>
これで、i18nの付いた、セレクトボックスを再現出来ました。
2ファイルを上書きするだけで、i18nを実現出来たので、typus標準に組み込んでしまいたいのですが、typus自体は、必要最小限のgem以外は取り込まない方針なのでなかなか難しいのでしょうね。