devise更新用户没有密码

我想在devise中更新用户属性而不用密码。 这种情况是,如果密码和密码确认字段不是空白的,那么我需要devise错误,如果它们是空白的,那么其他用户属性需要更新。 我怎么能这样做devise?

提前致谢!

这是你在找什么? 来自Devise wiki

允许用户在不提供密码的情况下编辑其帐户

它显示了如何对导轨3和导轨4执行此操作

=======================

约翰的解决scheme是一个更简单的select

我认为这是一个更好的解决scheme:

 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+,你可以覆盖你的subclassed控制器中的update_resource。 以下是最初提出的问题的一个例子:

 class MyRegistrationsController < Devise::RegistrationsController protected def update_resource(resource, params) resource.update_without_password(params) end end 

我解决了这个问题如下:如果表单提交的密码,然后需要填写current_password字段或forms更新没有密码和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"); } }); }); }); 

给用户一个checkbox来select他们是否要更新

另一个选项是如果用户没有表示要更新密码,则从表单中删除密码字段。 这是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 

所以如果用户是新的,他将被要求指定密码。 然而,存在的用户只有在填写密码或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

除了检查是否存在(空白string返回false)

这里是关于我在这个问题上的pull请求的讨论: https : //github.com/plataformatec/devise/pull/3920

如果你想devise检查当前密码只有当用户试图改变密码这意味着你可以改变其他属性,而不提供当前的密码 ):

 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'} 

routes.rb

如果您仍然希望支持更改密码但将其设置为可选,请检查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存在,您可以继续并更新密码,否则忽略它并更新而不使用密码。

这是更多的业务逻辑,所以我不会把太多的代码放在控制器中。 我build议覆盖Devise::Models::Validatable#password_required? 在你的模型中:

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

我有完全相同的问题,这是我提出的解决scheme,并相信我的工作原理。 我所做的是创build第二个user_params方法,并将其命名为user_params_no_pass看看:这里发生的事情是,当密码需要更新时,pipe理员将提供密码,否则将密码留空。 当密码为空时,使用user_params else 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