i18nのhuman系メソッドはモデルだけでなくインスタンスからも呼び出せる

i18nでモデル名やカラム名を参照するhuman系メソッドはモデルからしか呼び出せないと思っていましたが、インスタンスからも呼び出せるようです。

human系メソッドとは?

i18nActiveRecordのモデル名、カラム名を参照するメソッド。メソッド名が長いので勝手にhuman系と呼びました。 次のような形で翻訳情報を参照することができます。

モデル名: Model.model_name.human カラム名: Model.human_attribute_name(attribute)

Rails 国際化(i18n)API - Railsガイド

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.rbcreate アクションから参照します。

# 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.humanmodel: Book.model_name.human と同義です。 今回の場合ですとredirect_to @book@book インスタンスを指定しているので翻訳情報も同じ@book インスタンスからメソッドを呼んだ方が読み易いのではないかなと思います。

まとめ

なかなか文章化しにくい内容でしたが、可読性という視点でメソッドの呼び出し元を考えたことが無かったので良い勉強になりました。 少しでも読みやすいコードが書けるように今後も意識していこうと思います。

参照

Rails 国際化(i18n)API - Railsガイド

i18nで多言語化する - karlley's tech blog

Rails モデル名の i18n のもう一つの方法 - Qiita