私の目標は、(ログインしている) ユーザーが、ページから移動せずに、電子メールまたはパスワードを (別々のフォームで、両方を同時にではなく) 更新することを選択できるプロファイル ページを作成することです。
メールの更新は、新しいメール アドレスを入力して [変更を保存] 送信ボタンをクリックするだけで簡単に行えます。
パスワードを更新するには、ユーザーは古いパスワード、新しいパスワード、および新しいパスワードの確認を入力し、[パスワードの更新] ボタンを押す必要があります。問題は update_pwd メソッドにあるはずです。
users_controller.rb
# ...
def edit # template: edit.html.erb
@user = User.find(current_user)
end
def update_email
@user = User.find(current_user)
if params[:commit] == 'Save Changes'
if @user.update_attributes(user_params_email)
redirect_to me_url
flash[:notice] = "Your changes have been saved"
else # either invalid or taken
render :edit
end
else
render :edit
end
end
def update_pwd
@user = User.find(current_user)
if params[:commit] == 'Update Password'
if @user.update_attributes(user_params_pwd) && User.find_by(username: current_user.username).try(:authenticate, params[:current_password])
redirect_to me_url
flash[:notice] = "Password updated!"
else
flash.now[:alert] = @user.errors.full_messages[0]
render :edit
end
else
render :edit
end
end
private
#def user_params
#params.require(:user).permit(:id, :username, :email, :password, :password_confirmation)
#end
def user_params_email
params.require(:user).permit(:email)
end
def user_params_pwd
params.require(:user).permit(:password, :password_confirmation, :current_password)
end
edit.html.erb
<%= form_for(current_user, :url => {:controller => 'users', :action => 'update_email'}) do |f| %>
<% if @user.errors.any? %>
<% for message in @user.errors.full_messages %>
<li><%= message %></li>
<% end %>
<% end %>
<p> Current Email: <%= current_user.email %> </p>
<p> New Email: <%= f.text_field :email %> </p>
<%= f.submit "Save Changes" %>
<% end %>
<%= form_for(current_user, :url => {:controller => 'users', :action => 'update_pwd'}) do |g| %>
<p>Old Password<br>
<%= password_field_tag :current_password, params[:password] %></p>
<p>New Password<br>
<%= g.password_field :password %></p>
<p>Confirm New Password<br>
<%= g.password_field :password_confirmation %></p>
<%= g.submit "Update Password" %>
<% end %>
ルート.rb
# ...
get '/me' => 'users#edit'
patch '/me' => 'users#update_email'
patch '/me' => 'users#update_pwd'
# ...
これで、電子メールの更新を希望どおりに機能させることができました (必要なエラー メッセージ/検証などを使用)。ただし、パスワードの更新ボタンをクリックすると、ビューがレンダリングされますが、何も起こりません。代わりに、 update_email 関数が呼び出されているように見えます。
Started PATCH "/me" for ::1 at 2015-05-20 10:34:31 -0500
Processing by UsersController#update_email as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"msEsj6yxfdrbXjjdm6cH3JamrFU8R1EoZ5asmE831GSxLwpiiIW/wmGrr9HiQxFDySJtW5MKK6Ezq9hZaMNFtA==", "current_password"=>"[FILTERED]", "user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Password"}
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1←[0m [["id", 2]]
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`. (called from update_email ...)
user.rb
# ...
has_secure_password
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }
validates_uniqueness_of :email
validates :password, length:{ minimum: 8 }, on: :create
validates :password_confirmation, presence: true, on: :create
# ...
application_controller.rb
# ...
helper_method :current_user
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
rescue ActiveRecord::RecordNotFound
end
エラーログ (上記参照)
Started PATCH "/me" for ::1 at 2015-05-20 10:34:31 -0500
Processing by UsersController#update_email as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"msEsj6yxfdrbXjjdm6cH3JamrFU8R1EoZ5asmE831GSxLwpiiIW/wmGrr9HiQxFDySJtW5MKK6Ezq9hZaMNFtA==", "current_password"=>"[FILTERED]", "user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Password"}
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1←[0m [["id", 2]]
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`. (called from update_email ...)