notice_message, alert_message: 小林研 Rails Tips (17)

はじめに

Rails Tips の 17 回目です。しばらく shared_example が続いたので、この後の request_spec のためのヘルパーメソッドを先に説明しておきたいと思います。

事前準備: I18n の設定

config/application.rb にデフォルトの locate を ja として登録しています。これにより config/locales/ の下の ja.yml からさまざまなメッセージを取り込むことができます。

config.i18n.default_locale = :ja

config/locales/models/ja.yml に以下のようにモデルの名前を設定してあります。

ja:
  activerecord:
    models:
      (中略)
      kurasu: クラス

また、config/locales/ja.yml には以下のように flash メッセージを用意しています。

ja:
  (中略)
  ### flash メッセージ
  flash:
    create:
      notice: "%{obj}を登録しました。"
      alert: "%{obj}の登録に失敗しました。"
    update:
      notice: "%{obj}を更新しました。"
      alert: "%{obj}の更新に失敗しました。"
    edit:
      alert: "%{obj}を編集する権限がありません。"
    destroy:
      notice: "%{obj}を削除しました。"
      alert: "%{obj}を削除する権限がありません。"
    show:
      alert: "%{obj}を表示する権限がありません。"
    copy:
      notice: "%{obj}を一括コピーしました。"
    duplicate:
      notice: "%{obj}を複製しました。"
    edit_status:
      create: "編集を開始します。"
      update: "編集状態を解除しました。"
    remove_all:
      notice: "%{obj}を全て削除しました。"
    append_all:
      notice: "%{obj}を一括登録しました。"
    update_all:
      notice: "%{obj}を一括更新しました。"
    permission_error:
      alert: "ページを表示する権限がありません。"

notice_message, alert_message

create, update, destroy などでは正常時に notice message を、異常時には alert message を表示することがあります。これらはだいたい定型メッセージになることが多いので、それを上の I18n で表示するようにしました。例えば、kurasu を作成する場合には、ja.flash.create.notice に「クラス」という文字列を渡す形になります。これを実現するためのメソッドが notice_message ヘルパーメソッドです。デフォルトで呼び出した action_name が自動的に設定されますが、強制的に別のアクション名を指定したい場合もあるため、acn として渡せるようにしています。notice_message はクラスを受け付け、その I18n の名前を human で取得します。これにより「クラスを作成しました。」という文字列が得られるわけです。

  # @param [Class] klass 表示するクラス
  # @return [String] 表示する notice message
  def notice_message(klass, acn = nil)
    I18n.t "flash.#{acn || action_name}.notice", **{obj: klass.model_name.human}
  end
  helper_method :notice_message

これにより、teacher_kurasus_controller の create におけるリダイレクトはこの notice_message を利用できます。action_name は自動的に設定されるので、update の場合でも全く同じ notice_message(Kurasu)でいいのが楽ですね。

redirect_to teacher_kurasus_path(gakka_id: @kurasu.gakka_id), notice: notice_message(Kurasu)

alert_message もキーワードが異なるだけで同じです。

  # @param [Class] klass 表示するクラス
  # @return [String] 表示する alert message
  def alert_message(klass, acn = nil)
    I18n.t "flash.#{acn || action_name}.alert", **{obj: klass.model_name.human}
  end

おわりに

notice_message と alert_message によって、コントローラにほとんど日本語を記述しなくてよくなりました。非常に便利なヘルパーメソッドだと思います。