6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

deviseのエラーメッセージがうまく表示されない。

Posted at

概要

deviseのエラーメッセージがうまく表示されないので、理由をなんとなく突き止めた。
解決とは言えないけど、decviseの仕組みが少しだけ理解できたので忘備録として残しておきます。

解決策

部分テンプレートを呼び出す時に、テンプレートに変数名をresourceから@モデル名に変更した。

エラーメッセージ
<%= render "devise/shared/error_messages", resource: resource %><%= render "devise/shared/error_messages", resource: @profile %>

deviseは複数のモデルのインスタンスを扱えるフレームワークなので、resourceでうまく処理できるみたいです。
本当は別の処理もありそうだけど、ここを@モデル名に変えたらうまくいきました。

その他のコード

ルーティング

ユーザー登録とプロフィール登録をウィザード形式にしているため、profileは'users/registration'コントローラーで処理させています。
※なんかここにエラーがでた理由が隠されていそうなんだけど詳しくは不明。

routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  devise_scope :user do
    get 'profiles', to: 'users/registrations#new_profile'
    post 'profiles', to: 'users/registrations#create_profile'
  end
end

テーブル設計

deviseを使って、usersテーブルとprofilesテーブルにユーザー情報を保存しようとしている。

schema.rb
# usersテーブルとprofielsテーブルはこんな感じ。

  create_table "profiles", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "favorite_beer"
    t.text "twitter_link"
    t.text "info"
    t.bigint "user_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["user_id"], name: "index_profiles_on_user_id"
  end

  
  create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "nickname", null: false
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

入力フォーム

プロフィール登録のビューはこんな感じ。
ここの部分テンプレートでエラーメッセージを呼び出しているが、そこにうまくprofilesテーブルの情報が渡せなかった様子。

new_profile
<h2>プロフィール登録</h2>
<%= form_with model: @profile, local: true do |f| %>
  <%= render "devise/shared/error_messages", resource: @profile %>

  <div class="field">
    <%= f.label :avatar %><br />
    <%= f.file_field :avatar %>
  </div>

  <div class="field">
    <%= f.label :favorite_beer %><br />
    <%= f.text_field :favorite_beer, autofocus: true, autocomplete: "favorite_beer" %>
  </div>

  <div class="field">
    <%= f.label :twitter_link %><br />
    <%= f.text_field :twitter_link, autocomplete: "twitter_link" %>
  </div>

  <div class="field">
    <%= f.label :info %><br />
    <%= f.text_area :info %>
  </div>

  <div class="actions">
    <%= f.submit "新規登録" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

エラーメッセージの呼び出しもと

部分テンプレートで呼び出しているdeviseのエラーメッセージは以下の通り

divese/shared/_error_messages.html.erb
<% if resource.errors.any? %>
<%# この↑の部分のresourceに@profileを渡した%>
  <div id="error_explanation">
    <h2>
      <%= I18n.t("errors.messages.not_saved", #ここら辺の記述はdevise.ja.ymlに記載がある
                 count: resource.errors.count,
                 resource: resource.class.model_name.human.downcase)
       %>
    </h2>
    <ul>
      <% resource.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

deviseを日本語化しているファイル

deviseは既に日本語化しているので、ymlファイルも日本語になっています。

config/locales/devise.ja.yml
ja:
  activerecord:
    attributes:
# ~省略~     
    models:
      user: ユーザ
      profile: プロフィール # ここも日本語化したかったので追記しました
# ~省略~
  errors:
    messages:
      already_confirmed: は既に登録済みです。ログインしてください。
      confirmation_period_expired: の期限が切れました。%{period} までに確認する必要があります。 新しくリクエストしてください。
      expired: の有効期限が切れました。新しくリクエストしてください。
      not_found: は見つかりませんでした。
      not_locked: は凍結されていません。
# このしたのnot_savedのところが部分テンプレートで呼び出されている様子
      not_saved:
        one: エラーが発生したため %{resource} は保存されませんでした。
        other: "%{count} 件のエラーが発生したため %{resource} は保存されませんでした。"

まとめ

今後まだまだ勉強していきたいと思います。
もしこの文章がとんでもない勘違いを含んでいましたら、ご指摘いただければと思います。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?