i18nでモデル名やカラム名を参照するhuman系メソッドはモデルからしか呼び出せないと思っていましたが、インスタンスからも呼び出せるようです。
human系メソッドとは?
i18nでActiveRecordのモデル名、カラム名を参照するメソッド。メソッド名が長いので勝手にhuman系と呼びました。 次のような形で翻訳情報を参照することができます。
モデル名: Model.model_name.human
カラム名: Model.human_attribute_name(attribute)
i18nで多言語化する - karlley's tech blog
このModel
の部分にモデル名だけでなくインスタンスからも同様にメソッドを呼び出すことができるという点が今回のポイントです。
モデルとインスタンスからメソッド呼び出し
Bookモデルの下記のような翻訳情報をhuman系のメソッドで参照します。
ja: activerecord: models: book: 書籍 attributes: book: title: 書籍名
モデルからhuman系メソッドの呼び出し。
$ rails c > Book.model_name.human #モデル名 => "書籍" > Book.human_attribute_name(:title) #カラム名 => "書籍名"
インスタンスから同様にhuman系のメソッドが呼び出せます。 この時、単体のインスタンス/インスタンスの集合どちらでも呼び出せます。
# 単体 > @book = Book.new... => #<Book:0x000000011149b8f0... > @book.model_name.human => "書籍" # 集合 > @books = Book.all => [#<Book:0x000000010778c708 ... > @books.model_name.human => "書籍" > @books.human_attribite_name(:title) => "書籍名"
human_attribute_name
メソッドは単体のインスタンスに対しては呼べないようなので下記はエラーになるようです。
> @book.human_attribute_name(:title) => NoMethodError
Rails モデル名の i18n のもう一つの方法 - Qiita
メリット
あまり自信はないですが次の2つのメリットがあるのではないかと思っています。
実用例
ja.yml
ファイルの翻訳情報をbooks_controller.rb
のcreate
アクションから参照します。
# ja.yml ja: activerecord: models: book: 書籍 attributes: book: title: 書籍名 controllers: common: create: # @book.model_name.human で取得したモデル名「書籍」を%{model}で展開 success: "%{model}が登録されました。"
# books_controler.rb def create @book = Book.new(book_params) if @book.save # @book.model_name.human でモデル名「書籍」を参照 # redirect_to @book, notice: t('controllers.common.create.success', model: Book.model_name.human) と同義 redirect_to @book, notice: t('controllers.common.create.success', model: @book.model_name.human) else render :new end end
モデル名展開用のmodel: @book.model_name.human
はmodel: Book.model_name.human
と同義です。
今回の場合ですとredirect_to @book
で@book
インスタンスを指定しているので翻訳情報も同じ@book
インスタンスからメソッドを呼んだ方が読み易いのではないかなと思います。
まとめ
なかなか文章化しにくい内容でしたが、可読性という視点でメソッドの呼び出し元を考えたことが無かったので良い勉強になりました。 少しでも読みやすいコードが書けるように今後も意識していこうと思います。