Разработать обновление пользователя без пароля
Я хочу обновить атрибуты пользователей без пароля в devise. Дело в том, что если поля пароля и подтверждения пароля не пусты, то мне нужно придумать ошибку, и если они пусты, то другие атрибуты пользователя должны быть обновлены. Как я мог сделать это с помощью devise?
спасибо заранее!
13 ответов:
Это то, что вы ищите? Из проекта Wiki
разрешить пользователям редактировать свою учетную запись без пароля
Он показывает, как это сделать для рельсов 3 и рельсов 4
=======================
Джон более простой вариант
Я думаю, что это гораздо лучшее решение:
if params[:user][:password].blank? && params[:user][:password_confirmation].blank? params[:user].delete(:password) params[:user].delete(:password_confirmation) end
Это позволяет вам не менять контроллер Devise, просто удалив поле пароля из ответа формы, если оно пустое.
просто не забудьте использовать это до
@user.attributes = params[:user]
или что вы используете в своейupdate
действие для установки новых параметров из формы.
Я думаю, что с Devise 3.2+ вы можете просто переопределить update_resource в вашем подклассе контроллера. Вот пример для первоначально заданного вопроса:
class MyRegistrationsController < Devise::RegistrationsController protected def update_resource(resource, params) resource.update_without_password(params) end end
Я решил эту проблему следующим образом: если форма отправки с паролем, то нужно заполнить поле current_password или форма обновляется без пароля и current_password
модель:
class User devise: bla-bla-bla attr_accessor :current_password end
в контроллере:
class Users::RegistrationsController < Devise::RegistrationsController layout 'application' def update self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key) # custom logic if params[:user][:password].present? result = resource.update_with_password(params[resource_name]) else result = resource.update_without_password(params[resource_name]) end # standart devise behaviour if result if is_navigational_format? if resource.respond_to?(:pending_reconfirmation?) && resource.pending_reconfirmation? flash_key = :update_needs_confirmation end set_flash_message :notice, flash_key || :updated end sign_in resource_name, resource, :bypass => true respond_with resource, :location => after_update_path_for(resource) else clean_up_passwords resource respond_with resource end end end
Я решаю эту проблему с моим интерфейсом. Есть два пути, которыми это может пойти.
отключите поля, если они пусты
этот бит jQuery отключает поля перед отправкой формы в случае, если они пусты. Для этого требуется определенный шаблон разметки, проверьте демо на Codepen.
$(".password-fields").each(function() { var $fields, $form; $form = $(this).parents("form"); $fields = $(this).find("input"); $form.on("submit", function() { $fields.each(function() { if ($(this).val() === "") { $(this).attr("disabled", "disabled"); } }); }); });
дать пользователю опцию, чтобы выбрать, если они хотят обновить
другой вариант-удалить пароль из формы, если пользователь не указал, что они хотят обновить свой пароль. Вот пример на CodePen.
$(".password-fields").each(function () { var $fields, $button, html; $fields = $(this); $button = $fields.prev(".update-password").find("input"); html = $fields.html(); $button .on("change", function () { if ( $(this).is(":checked") ) { $fields.html(html); } else { $fields.html(""); } }) .prop("checked", "checked") .click(); });
в любом случае, он не требует обновления самого приложения. Вы просто отправляете поля, которые хотите изменить.
Я вместо того, чтобы переопределить #password_required? метод внутри модели пользователя.
class User < ActiveRecord::Base devise :database_authenticatable, :validatable #, ... def password_required? if respond_to?(:reset_password_token) return true if reset_password_token.present? end return true if new_record? password.present? || password_confirmation.present? end end
поэтому, если пользователь является новым, он должен будет указать пароль. Однако пользователь exist должен будет указать пароль только в том случае, если он заполнит атрибуты password или password_confirmation.
Подробнее см.: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L33
моя реализация почти идентична оригинальный: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L53
за исключением того, что я проверяю наличие (который возвращает false для пустых строк)
вот обсуждение моего запроса на вытягивание по этому вопросу:https://github.com/plataformatec/devise/pull/3920
Если вы все еще хотите поддерживать изменение пароля, но сделать его необязательным, проверьте доступность
current_password
такие как:class MyRegistrationsController < Devise::RegistrationsController protected def update_resource(resource, params) if params[:current_password].blank? resource.update_without_password(params.except(:current_password)) else resource.update_with_password(params) end end end
таким образом, если current_password присутствует, вы можете продолжить и обновить пароль, иначе проигнорируйте его и обновите без пароля.
Если вы хотите придумать, чтобы проверить текущий пароль только тогда, когда пользователь пытается изменить пароль (это означает, что вы можете изменить другие атрибуты, без указания текущего пароля):
class RegistrationsController < Devise::RegistrationsController protected def update_resource(resource, params) if params[:password].blank? && params[:password_confirmation].blank? resource.update_without_password(params) else super end end end
также в модели:
attr_accessor :current_password
и не забывайте о
devise_for :users, controllers: {registrations: 'registrations'}
на маршруты.РБ.
Это больше бизнес-логики, так что я бы не положить слишком много кода в контроллер. Я предлагаю переопределить
Devise::Models::Validatable#password_required?
в вашей модели:def password_required? new_record? || password.present? || password_confirmation.present? end
у меня была точно такая же проблема и это решение я придумал и поверьте мне, это работает. Что я сделал, это создать второй
user_params
метод и назвал егоuser_params_no_pass
в любом случае взгляните: то, что происходит здесь, заключается в том, что администратор предоставит пароль, когда пароль должен быть обновлен, иначе оставьте пароль пустым. когда пароль пустuser_params_no_pass
используется ещеuser_params
. Я надеюсь, что это поможетdef update if @user.valid_password?(params[:user][:password]) respond_to do |format| if @user.update(user_params) format.html { redirect_to @user, notice: 'User profile was successfully updated.' } format.json { render :show, status: :ok, location: @user } else format.html { render :new } format.json { render json: @user.errors, status: :unprocessable_entity } end end else respond_to do |format| if @user.update(user_params_no_pass) format.html { redirect_to @user, notice: 'User profile was successfully updated without password.' } format.json { render :show, status: :ok, location: @user } else format.html { render :edit } format.json { render json: @user.errors, status: :unprocessable_entity } end end end end def destroy @user.destroy respond_to do |format| format.html { redirect_to users_url, notice: 'User was successfully destroyed.' } format.json { head :no_content } end end private def set_user @user = User.find(params[:id]) end def user_params params.require(:user).permit(:user_name, :first_name, :middle_name, :last_name, :dob, :gender, :race, :hispanic, :leader, :mentor, :student, :email, :organization_id, :password, :opus, :release_date, :days_to_release, :current_level, :is_active) end def user_params_no_pass params.require(:user).permit(:user_name, :first_name, :middle_name, :last_name, :dob, :gender, :race, :hispanic, :leader, :mentor, :student, :email, :organization_id, :opus, :release_date, :days_to_release, :current_level, :is_active) end
как обходной путь положить в вашей модели пользователя
def password_required? encrypted_password.blank? || encrypted_password_changed? end
Я нахожу это небольшое изменение кода выше легче следовать:
def update @user = User.find(params[:id]) method = if user_params[:password].blank? :update_without_password else :update_with_password if @user.send(method, user_params) redirect_to @user, notice: 'User settings were saved.' else render :edit end end
после долгих исследований вышеуказанных возможностей я, наконец, нашел решение, которое позволяет обновлять некоторые атрибуты без пароля, а некоторые с:
Я сделал вид для пользователей/редактирования.формат html.erb со следующей формой в нем.
<%= form_for(@user) do |f| %> <%= render 'shared/error_messages', object: f.object %> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> <%= f.submit "Save changes"%> <% end %>
я поставил стороны в стороны.РБ
resources :users, only: [:show, :index, :edit, :update]
Я сделал редактировать и обновлять методы в users_controller.РБ
def edit @user = current_user end def update @user = current_user if @user.update_attributes(user_params) flash[:success] = "Profile updated" redirect_to root_url else render 'edit' end end def user_params params.require(:user).permit(:name, :avatar, :whatsup) end
я использовал этот вид редактирования для изменений, которые не требуют пароля. Он пропускает устройство контроллер регистрации полностью потому, что я ссылаюсь на него с
edit_user_path(current_user)
Я также установил параметры так, что электронная почта и пароль не могут быть изменены здесь. Чтобы обновить пароль и электронную почту, я ссылаюсь на созданный на складе devise view:
edit_user_registration_path(current_user)
Я признаю, что это огромная работа, но ни одно из более простых решений не решило все вышеперечисленные проблемы.