ruby on rails - tutorial - Настройка пользователя без пароля




rails devise настройка (9)

Я хочу обновлять атрибуты пользователей без пароля. Дело в том, что, если поля подтверждения пароля и пароля не пустые, мне нужно разработать ошибку, и если они пусты, тогда необходимо обновить другие пользовательские атрибуты. Как я мог это сделать с помощью?

Заранее спасибо!


Вместо этого я переопределяю #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

Поэтому, если пользователь новый, ему потребуется указать пароль. Однако пользователю необходимо указать пароль только в том случае, если он заполняет либо пароль, либо атрибуты 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, вы можете продолжить и обновить пароль, иначе проигнорировать его и обновить без пароля.


Как обходное решение в вашей модели пользователя

def password_required?
  encrypted_password.blank? || encrypted_password_changed?
end

После большого изучения вышеуказанных возможностей я наконец нашел решение, которое позволяет вам обновлять некоторые атрибуты без пароля, а некоторые с помощью:

Я сделал вид для пользователя / edit.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 %>

Я установил маршруты в routes.rb

resources :users, only: [:show, :index, :edit, :update]

Я создал методы редактирования и обновления в users_controller.rb

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)

Я также установил параметры, чтобы здесь нельзя было изменить адрес электронной почты и пароль. Чтобы обновить пароль и адрес электронной почты, я ссылаюсь на созданный вами проект:

edit_user_registration_path(current_user)

Я признаю, что это огромная работа, но ни один из более простых решений не разрешил все вышеупомянутые проблемы.


Это больше бизнес-логика, поэтому я не ставил бы слишком много кода в контроллер. Я предлагаю переопределить Devise::Models::Validatable#password_required? в вашей модели:

def password_required?
  new_record? || password.present? || password_confirmation.present?
end


Я думаю, что это гораздо лучшее решение:

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 чтобы установить новые параметры из формы.


Я решаю эту проблему с моим интерфейсом. Есть два пути, которыми это может пойти.

Отключите поля, если они пусты

Этот бит 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();
});

В любом случае он не требует обновления для самого приложения. Вы просто отправляете поля, которые хотите изменить.


Я считаю, что это небольшое изменение в коде выше проще:

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




devise