はじめに
モデルの状態を表す日本語文字列をどこにおくべきか迷ってました。
同僚からi18nとenumとactive_decoratorを使うことを提案されて、試してみたらもやもやが晴れたのでまとめました。
環境
- ruby 2.2.1
- rails 4.2.3
- サンプルソース
enumはrails4.1から導入されたので、それ以降ならたぶん大丈夫です。
なんかもっさりしたコード
app/models/article.rb
class Article < ActiveRecord::Base
STATUS_DRAFT = 0
STATUS_PUBLIC = 1
STATUS_DISABLED_BY_ADMIN = 2
STATUS_LABELS = {
STATUS_DRAFT => "下書き",
STATUS_PUBLIC => "公開中",
STATUS_DISABLED_BY_ADMIN => "管理者により非公開中",
}
def active?
status == STATUS_PUBLIC
end
def status_label
STATUS_LABELS[status]
end
end
ステータスを数値型にしています。
ステータス値を意味ある文字列で扱えるように、定数を定義したり、
ビューでの表示用の日本語ラベルを定義したりしています。
いろいろモデルに固まってて、微妙でした。
書きなおしたコード
app/models/article.rb
class Article < ActiveRecord::Base
enum status: { draft: 0, opened: 1, closed_by_admin: 2 }
def active?
opened?
end
end
ステータスをenumで定義して…
config/application.rb
config.i18n.default_locale = :ja
デフォルトのロケールをja
にして…
config/locales/application_ja.yml
ja:
articles:
statuses:
draft: 下書き
opened: 公開中
closed_by_admin: 管理者により非公開中
モデル内で定義してあった日本語ラベルをi18nに移して…
gem "active_decorator"
active_decoratorを導入して…
app/decorators/artcible.rb
module ArticleDecorator
def status_label
t("articles.statuses.#{status}")
end
def status_labels
Article.statuses.map {|k, v| [t("articles.statuses.#{k}"), k] }
end
end
ビューでだけ使いそうなラベル表示用のメソッドをdecoratorに移しました。
気持ちよくなったところ
- 自分で作らなくても、ステータス設定や問い合わせが
#opened!
や#opened?
でできること - 日本語の定数がモデルから排除できたこと
- 表示用のメソッドをモデルから排除できたこと