Не удалось найти пользователя с id = update_password с помощью Devise

64
7

Я использую приложение для Rails и по разным причинам мне нужно добавить настраиваемое изменение пароля, используя решение 3 здесь: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users -в-редактировать-их-пароль

Я просмотрел различные другие вопросы и попытался расширить свои маршруты несколькими способами, но всегда появляется URL-адрес/users/update_password (без переданного параметра) или /users/update_password.254 (с переданным параметром). Мне это нужно /users/254/update_password.

Вот контроллер пользователей, с которым я работаю (соответствующими методами являются update_password и user_params).

class UsersController < ApplicationController
inherit_resources
load_and_authorize_resource
before_filter :authenticate_user!

def destroy
name = @user.to_s
destroy!(notice: "User #{@user.to_s} was deleted.")
end

def edit
@user = current_user
end

def update_password
@user = User.find(current_user.id)
if @user.update_with_password(user_params)
sign_in @user, :bypass => true
redirect_to root_path
else
render "edit"
end
end

private

def build_resource_params
[params.fetch(:user, {}).permit(:name, :email, :phone_number, :password, :password_confirmation).tap do |p|
p[:institution_pid] = build_institution_pid if params[:user][:institution_pid]
p[:role_ids] = build_role_ids if params[:user][:role_ids]
end]
end

def build_institution_pid
institution = Institution.find(params[:user][:institution_pid])
authorize!(:add_user, institution)
institution.id
end

def build_role_ids
[].tap do |role_ids|
roles = Role.find(params[:user][:role_ids].reject &:blank?)
roles.each do |role|
authorize!(:add_user, role)
role_ids << role.id
end
end
end

def user_params
params.required(:user).permit(:password, :password_confirmation, :current_password)
end

end

Это соответствующая часть маршрутов.rb

devise_for :users

resources :users do
collection do
get 'password'
put 'update_password'
end
end

Это представление, которое я создал для этого:

<div class="page-header">
<h1>Change Password</h1>
</div>

<%= form_for(@user, :url => { :action => "update_password" } ) do |f| %>
<div class="field">
<%= f.label :password, "Password" %><br />
<%= f.password_field :password, :autocomplete => "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
</div>
<div class="action_container">
<%= f.submit %>
</div>

И это ссылка: (в настоящее время с параметром, но я тоже пробовал)

<li><%= link_to "Change Password", update_password_users_path(current_user) %></li>

Когда я нажимаю эту ссылку, я перенаправляюсь на страницу, в которой говорится, что ActiveRecord :: RecordNotFound в ShowController # show, Не удалось найти пользователя с id = update_password.

Я старался внимательно следить за инструкциями, и я пытался несколько раз поиграть с маршрутами, чтобы заставить его работать, и я довольно потерялся в этот момент. Кто-нибудь видел это раньше и может помочь? Благодарю!

спросил(а) 2021-01-19T18:02:45+03:00 6 месяцев назад
1
Решение
64

Для достижения того, что вам нужно, вы будете иметь следующие маршруты:

resources :users do
patch 'update_password', on: :collection
get 'edit_password', on: :member
end

Затем вы добавите ссылку, которая приведет пользователя к update password form. Ссылка должна выглядеть следующим образом:

<li><%= link_to "Change Password", edit_password_user_path(current_user) %></li>

Ссылка приведет к users/edit_password.html.erb:

<div class="page-header">
<h1>Change Password</h1>
</div>

<%= form_for(@user, :url => { :action => "update_password" } ) do |f| %>
<div class="field">
<%= f.label :password, "Password" %><br />
<%= f.password_field :password, :autocomplete => "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
</div>
<div class="action_container">
<%= f.submit %>
</div>
<% end %>

Когда форма отправлена, это вызовет update_password в UsersController. Вот код для контроллера:

class UsersController < ApplicationController

def edit_password
@user = current_user
end

def update_password
@user = User.find(current_user.id)
if @user.update_with_password(user_params)
sign_in @user, :bypass => true
redirect_to root_url
else
render "edit_password"
end
end

private

def user_params
params.required(:user).permit(:password, :password_confirmation, :current_password)
end

end

ответил(а) 2021-01-19T18:02:45+03:00 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема