【Rails】deviseのエラーメッセージを日本語化してBootstrapでスマートに表示する

【Railsでアプリ開発中】プログラミング初心者の勉強ブログ #47

RailsのGem「devise」は大変便利です。なんかもう全部自動で作ってくれちゃいます。しかし、少しカスタマイズするとなると、deviseがどの様な仕組みなのか理解しなければなりません。今回はdeviseで実装したログインに関するエラーメッセージをちゃんと日本語化し、Bootstrapでスマートに表示したいと思います。

はじめに

この記事は、railsフレームワークでオリジナルwebアプリ「免許学科試験学習サイト」作成中の僕が、プログラミングをしている中で気づいたことや学んだことを書いております。プログラミング初心者なので知識は少ないですが、現在通っているプログラミングスクール「DIVE INTO CODE」で学んでいることや、ネットで見つけた様々な記事を参考に記事を作成しております。

 

目次

[toc]

 

deviseとは

定義

「devise」とは、「Railsフレームワークで利用できるGemの1つ」であり、「ログイン機能に関するコードが用意されてるもの」です。Railsは、作成したブログアプリ等に対し、自らコーディングすることでもログイン機能を実装することが可能ですが、「devise」をRails内でインストールする事で、自らコードを書き込まなくてもログイン機能の実装が行えます。

deviseの必要性

「ログイン機能を実装する」ってRails初学者の登竜門みたいな感じですが、言っても色々なメソッドが必要になります。入力内容が合わない(メールアドレスが末尾が「.com」とか「ne.jp」とかでない)ときに入力内容を弾くコードを書いたり、リアルタイムでログインしているユーザーのidを取得するためのメソッドをコーディングしたりと、一回一回全部1から実装していくのは時間がかかります。ましてや「パスワードを忘れてしまった方」への救済措置や、今回取り上げる「エラーメッセージ」なども実装するとなると、deviseをうまく利用して行く必要性は十分にあります。

いきなりログイン機能を「devise」使って実装し始めてしまうと、ログインの仕組みについて、確かに理解が追いつかないかもしれません。最初は1から自分でコーディングして理解する必要があります。しかし、徐々に「devise」を使いこなせるようにシフトして行くことで開発にかかる時間は格段に下がります。本格的に一人でアプリ開発をするためには、「devise」の理解は必須だと考えます。

 

今回の実装

deviseのエラーメッセージを日本語化してBootstrapできれいに表示します。

エラーメッセージ

 

deviseのエラーメッセージ表示

deviseエラーメッセージ表示コードは2パターンある

「devise」にはデフォルトでエラーメッセージを表示させる機能が備わってます。その機能に対応するRails内に用意されているオプションが「notice」と「alart」で、

<%= notice %>
<%= alert %>

この様にHTMLに書くことでエラーが表示されます。そしてもう一つ、

<%= devise_error_messages! %>

これもログイン関係のエラーを表示させるコードです。同様にHTMLにRuby文を直書きでエラーが表示されます。

「devise_error_messages!」はviews/deviseディレクトリ内の中で使われるエラーメッセージコードです。(一部sessions/new.html.erbでは記入がなく、エラーメッセージは<%= alert %>の方で表示されているが理由はわかりませんでした。)

 

なぜ分けたか。

 

「notice」と「alart」は、

Railsの「redirect_to」メソッドのオプションとして、Rails内に元から用意されているもの。

 

一方で、「devise_error_messages!」は、

「devise」をインストールした際に生成されたメソッド。

 

という違いがあるから。

 

とにかく細かくはわかりませんが、deviseエラーメッセージには「Railsの機能使ってメッセージ出すよ」パターンと「devise専用メソッド使うよ」パターンの2つが存在します。

エラーメッセージをきれいに表示させるためには、この違いを意識する必要があります。

 

実際にどこで違いが現れるか

今回困った部分が、「devise_error_messages!」パターンのエラーメッセージのBootstrapでの装飾です。

 

Railsオプションである「notice」と「alart」は、以下のようにhtml.erbファイルに直接Bootstrapをかけることで解決します。

<!DOCTYPE html>
<html>
  #省略
  <body>
  #省略
    <% if notice %>
        <div class="alert alert-info alert-dismissible" role="alert">
          <button type="button" class="close" data-dismiss="alert">
            <span aria-hidden="true">&times;</span>
            <span class="sr-only">close</span>
          </button>
          <%= notice %>
        </div>
    <% end %>
    <% if alert %>
    <div class="alert alert-danger alert-dismissible" role="alert">
      <button type="button" class="close" data-dismiss="alert">
        <span aria-hidden="true">&times;</span>
        <span class="sr-only">close</span>
      </button>
      <%= alert %>
    </div>
    <% end %>
  #省略
  </body>
</html>

 

エラーメッセージ(alart)

 

一方で 「devise_error_messages!」は同じようにやってもうまくいきません。deviseのインストールで生成されたメソッドなので、メソッドの中身はわかりませんが、とにかく同じ要領ではBootstrapが効きませんでした。

 

調べました。

[blogcard url=”https://qiita.com/inodev/items/d61539b86968f1274ef8″]

ありました。僕の求めてた情報全てここにありました。

 

deviseのヘルパーを作って”devise_error_messages!”をオーバーライドした箇所で整形する方法とのことです。

devise内で書かれた「devise_error_messages!」メソッドでコーディングされているクラスを上書きする事で解決するようです。

 

オーバーライドとは、なんですか?

 

調べました。

 

オーバーライドとは、親クラスのメソッドを子クラスで上書きすること。

[blogcard url=”https://wa3.i-3-i.info/word138.html”]

ありました。わかりやすいです。

 

ちょっとやったことないコード連発されたので、まだあまり理解できてませんが、「helpers/devise_helper.rb」を作成し、以下を書くことでオーバーライドがされるようです。

module DeviseHelper
  def devise_error_messages!
    return "" if resource.errors.empty?

    html = ""
    messages = resource.errors.full_messages.each do |errmsg|
      html += <<-EOF
      <div class="alert alert-danger alert-dismissible" role="alert">
        <button type="button" class="close" data-dismiss="alert">
          <span aria-hidden="true">&times;</span>
          <span class="sr-only">close</span>
        </button>
        #{errmsg}
      </div>
      EOF
    end
    html.html_safe
  end

  def devise_error_messages?
    resource.errors.empty? ? false : true
  end

end

エラーメッセージ(devise_error_messages!)

 

エラーメッセージの日本語化

もともと日本語化については設定を行なっていたのですが、日本語化される箇所とされないで翻訳エラー出る箇所があったので原因を探してました。(アカウント作成時、同じメールアドレスで登録しようとしたときのエラーメッセージなどが翻訳エラーになってました。)

以下の記事で解決したんですが、

[blogcard url=”https://qiita.com/shizuma/items/a52fd0ef5b60d61fa330″]

 

当初使っていた日本語翻訳。

for devise 4.2.0

ここの内容で「ja.yml」ファイルを作成すると、少し翻訳が不足になってるようです。

“は既に使用されています。”
“が入力されていません。”
“は%{count}文字以上に設定して下さい。
“は%{count}文字以下に設定して下さい。”
“は有効でありません。”
“が内容とあっていません。”

一番下にこれを追加すると完璧です。

 

まとめるとこうなります。

config/locales/devise.ja.yml

ja:
  devise:
    confirmations:
      confirmed: 'アカウントを登録しました。'
      send_instructions: 'アカウントの有効化について数分以内にメールでご連絡します。'
      send_paranoid_instructions: "あなたのメールアドレスが登録済みの場合、本人確認用のメールが数分以内に送信されます。"
    failure:
      already_authenticated: 'すでにログインしています。'
      inactive: 'アカウントが有効化されていません。メールに記載された手順にしたがって、アカウントを有効化してください。'
      invalid: "%{authentication_keys} もしくはパスワードが不正です。"
      locked: 'あなたのアカウントは凍結されています。'
      last_attempt: 'あなたのアカウントが凍結される前に、複数回の操作がおこなわれています。'
      not_found_in_database: "%{authentication_keys} もしくはパスワードが不正です。"
      timeout: 'セッションがタイムアウトしました。もう一度ログインしてください。'
      unauthenticated: 'アカウント登録もしくはログインしてください。'
      unconfirmed: 'メールアドレスの本人確認が必要です。'
    mailer:
      confirmation_instructions:
        subject: 'アカウントの有効化について'
      reset_password_instructions:
        subject: 'パスワードの再設定について'
      unlock_instructions:
        subject: 'アカウントの凍結解除について'
      password_change:
        subject: 'パスワードの変更について'
    omniauth_callbacks:
      failure: "%{kind} アカウントによる認証に失敗しました。理由:(%{reason})"
      success: "%{kind} アカウントによる認証に成功しました。"
    passwords:
      no_token: "このページにはアクセスできません。パスワード再設定メールのリンクからアクセスされた場合には、URL をご確認ください。"
      send_instructions: 'パスワードの再設定について数分以内にメールでご連絡いたします。'
      send_paranoid_instructions: "あなたのメールアドレスが登録済みの場合、パスワード再設定用のメールが数分以内に送信されます。"
      updated: 'パスワードが正しく変更されました。'
      updated_not_active: 'パスワードが正しく変更されました。'
    registrations:
      destroyed: 'アカウントを削除しました。またのご利用をお待ちしております。'
      signed_up: 'アカウント登録が完了しました。'
      signed_up_but_inactive: 'ログインするためには、アカウントを有効化してください。'
      signed_up_but_locked: 'アカウントが凍結されているためログインできません。'
      signed_up_but_unconfirmed: '本人確認用のメールを送信しました。メール内のリンクからアカウントを有効化させてください。'
      update_needs_confirmation: 'アカウント情報を変更しました。変更されたメールアドレスの本人確認のため、本人確認用メールより確認処理をおこなってください。'
      updated: 'アカウント情報を変更しました。'
    sessions:
      signed_in: 'ログインしました。'
      signed_out: 'ログアウトしました。'
      already_signed_out: '既にログアウト済みです。'
    unlocks:
      send_instructions: 'アカウントの凍結解除方法を数分以内にメールでご連絡します。'
      send_paranoid_instructions: 'アカウントが見つかった場合、アカウントの凍結解除方法を数分以内にメールでご連絡します。'
      unlocked: 'アカウントを凍結解除しました。'
  errors:
    messages:
      already_confirmed: 'は既に登録済みです。ログインしてください。'
      confirmation_period_expired: "の期限が切れました。%{period} までに確認する必要があります。 新しくリクエストしてください。"
      expired: 'の有効期限が切れました。新しくリクエストしてください。'
      not_found: 'は見つかりませんでした。'
      not_locked: 'は凍結されていません。'
      not_saved:
        one: "エラーが発生したため %{resource} は保存されませんでした:"
        other: "%{count} 件のエラーが発生したため %{resource} は保存されませんでした:"
      taken: "は既に使用されています。"
      blank: "が入力されていません。"
      too_short: "は%{count}文字以上に設定して下さい。"
      too_long: "は%{count}文字以下に設定して下さい。"
      invalid: "は有効でありません。"
      confirmation: "が内容とあっていません。"

 

まとめ

またフロント分野で書いてしまいました。

どうでもいい話しますけど、「i18n」ってあるじゃないですか。「Internationalization(国際化)」の略で。この略し方なんだよって思いませんか。

Iとnの間に文字が18個あるから「i18n」。

いやもう、厚切りジェイソンがネタにするレベルだと思うんですよ。ホワイナメックピーポーですよ。

 

他にもあるのかなと思って調べたら「ヌメロニム」って言う略し方みたいで。ちゃんとした名前付いてたっていう。

[blogcard url=”https://ja.wikipedia.org/wiki/ヌメロニム”]

 

 

まあそれだけです。

以上ありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA