ユーザー登録機能のあるサイトを作っていて、ユーザー情報としてデータベースのテーブルにはユーザー名、メールアドレス、パスワードの情報を持たせています。バリデーションはどのカラムもpresence: true としていて、ユーザー情報(ユーザー名とメールアドレスの変更)の編集ページを作り、ユーザー名、メールアドレスのフォームとアクションを書いたのですが、submitボタンを押すとパスワードが空であるバリデーションエラーが出てしまいます。
パスワードは元のデータベースにあるものを使い、ユーザー名、メールアドレスだけを更新するにはどうすれば良いでしょうか?
編集ページのビュー <div class="main users-edit"> <h1>ユーザー情報の編集</h1> <div class="form"> <div class="form-body"> <% @user.errors.full_messages.each do |message| %> <div class="form-error"> <%= message %> </div> <%end%> <%= form_with model: @user, local: true do |form| %> <div class="field"> <%= form.label :ユーザー名 %> <%= form.text_field :name, placeholder: "ユーザー名" %> </div> <div class="field"> <%= form.label :メールアドレス %> <%= form.text_field :email, placeholder: "メールアドレス" %> </div> <div class="actions"> <%= form.submit "編集する" %> </div> <% end %> </div> </div> </div>
アクション def edit @user = User.find_by(id: params[:id]) end def update @user = User.find_by(id: params[:id]) if @user.update(user_params) flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else render("users/edit") end end private def user_params params.require(:user).permit(:name, :email, :password) end
/models/user.rb class User < ApplicationRecord has_secure_password validates :name, {presence: true} validates :email, {presence: true, uniqueness: true} validates :password, {presence: true} end
/user_controller.rb class UsersController < ApplicationController before_action :authenticate_user, {only: [:index, :show, :edit, :update]} before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]} before_action :ensure_correct_user, {only: [:edit, :update]} def index @users = User.all end def show @user = User.find_by(id:params[:id]) end def new @user = User.new end def create @user = User.new(user_params) if @user.save session[:user_id] = @user.id flash[:notice]="ユーザー登録が完了しました" redirect_to("/users/#{@user.id}") else render("users/new") end end def edit @user = User.find_by(id: params[:id]) end def update @user = User.find_by(id: params[:id]) if @user.update(user_params) flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else render("users/edit") end end def login_form end def login @user = User.find_by(email: params[:email]) if @user && @user.authenticate(params[:password]) session[:user_id] = @user.id flash[:notice] = "ログインしました" redirect_to("/posts") else @error_message = "メールアドレスまたはパスワードが間違っています" @email = params[:email] @password = params[:password] render("users/login_form") end end def logout session[:user_id] = nil flash[:notice] ="ログアウトしました" redirect_to("/login") end def ensure_correct_user if @current_user.id != params[:id].to_i flash[:notice] = "権限がありません" redirect_to("/posts") end end def update_name_and_email @user = User.find_by(id: params[:id]) if @user.update_attributes(name: params[:name], email: params[:email]) flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else render("users/edit") end end private def user_params params.require(:user).permit(:name, :email, :password) end end
schema.rb ActiveRecord::Schema.define(version: 2021_02_14_124745) do create_table "posts", force: :cascade do |t| t.string "title" t.text "content" t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "img" end create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "password_digest" end end
以下のコードを質問文に追記してほしいです。
app/models/user.rb
app/controllers/user_controller.rb
db/schema.rb
何故かというと、ちゃんとした回答をするために、
・Userクラスに「has_secure_password」を定義しているかどうか
・必須以外の検証の内容(パスワードは8文字以上とか、確認のためにパスワードは2回入力するとか)
などを把握しておきたいからです。
ちなみに、「今作っているページではパスワードを変更しないけど、あとからパスワード変更用ページを作る予定」という認識であってますか?
つまり、「更新時は絶対にパスワードのバリデーションを行わない」のではなく、「画面によって、更新時のパスワードのバリデーションが必要だったり不要だったりする」と考えて良いですか?
コメントありがとうございます。遅くなってしまい申し訳ありません。
コードの追記をしましたのでご確認いただければと思います。
はい。プロフィールの編集のような感覚でひとまず名前とメールアドレスの編集機能を実装しようとしていて、まだ深く理解できていないbcryptを使っていたりするのでパスワードは慎重に扱うべきかと思い、このページでは編集せず、新規登録時に保存されているものをそのまま使いたいと考えていました。エラー内容を見る限り、フォームに入力された新しいユーザー名、メールアドレスとともに、パスワードの情報もnilとして送信されてしまっている結果バリデーションにかかってしまっているように思うのですがどうでしょうか?
実現したい機能としては、登録されたユーザー名、アドレス、パスワードのなかの、ユーザー名とアドレスの二つだけを更新するページを作りたいです。
shinoharat2さんのおっしゃる「画面によって、更新時のパスワードのバリデーションが必要だったり不要だったりする」という認識で考えています。
回答2件
あなたの回答
tips
プレビュー