无需密码即可更新`User`属性

ste*_*392 26 passwords validation ruby-on-rails update-attributes

现在,用户可以编辑一些属性,而无需输入密码,因为我的验证设置如下:

validates :password, :presence =>true, :confirmation => true, :length => { :within => 6..40 }, :on => :create
validates :password, :confirmation => true, :length => { :within => 6..40 }, :on => :update, :unless => lambda{ |user| user.password.blank? } 
Run Code Online (Sandbox Code Playgroud)

但是,在用户执行此操作后,将删除其密码 - update_attributes将其密码更新为"".这是我的更新定义:

def update

    if @user.update_attributes(params[:user])
        flash[:success] = "Edit Successful."
        redirect_to @user
    else
        @title = "Edit user"
        render 'edit'
    end
end
Run Code Online (Sandbox Code Playgroud)

我也尝试使用另一种使用update_attribute的定义:

def save_ff
    @user = User.find(params[:id])
    @user.update_attribute(:course1, params[:user][:course1] )
    @user.update_attribute(:course2, params[:user][:course2] )
    @user.update_attribute(:course3, params[:user][:course3] )
    @user.update_attribute(:course4, params[:user][:course4] )
    redirect_to @user 
end 
Run Code Online (Sandbox Code Playgroud)

但出于某种原因,这是做同样的事情.如何在不更改密码的情况下更新某些用户属性?谢谢!

apn*_*ing 22

我没有意识到我昨天给你的解决方案会导致这个问题.抱歉.

好吧,从设计中获取灵感,您应该以这种方式更新控制器:

def update
  params[:user].delete(:password) if params[:user][:password].blank?
  if @user.update_attributes(params[:user])
    flash[:success] = "Edit Successful."
    redirect_to @user
  else
    @title = "Edit user"
    render 'edit'
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 我不会为了你的舒适而更新我多年前写的答案.我的回答是正确的,很多人都是.我是Rails的最大贡献者,答案超过1.5k,你认为我能管理它们吗?你愿意付钱给我吗?一个问题在其背景下具有价值,答案也是如此.对不起,你不能低估它 (9认同)
  • 听起来像一个国王joffreys说话不是一个严峻的...我带着你愉快的责备力量离开.继续劝阻别人帮助别人 (2认同)

cbe*_*ian 12

这篇博客文章展示了你想要做的事情的原则.

未显示但可能有用的是向模型添加访问器:

attr_accessor   :new_password, :new_password_confirmation
attr_accessible :email, :new_password, :new_password_confirmation
Run Code Online (Sandbox Code Playgroud)

并在用户提供新密码的条件下提供所有所需的验证.

  validates :new_password,  :presence => true, 
                            :length   => { :within => 6..40 }, 
                            :confirmation => true, 
                            :if       => :password_changed?
Run Code Online (Sandbox Code Playgroud)

最后,我会添加一个检查,看看是否已设置encrypted_pa​​ssword以确定是否"password_changed?" 为了在新记录上要求密码.

  def password_changed?
    !@new_password.blank? or encrypted_password.blank?
  end
Run Code Online (Sandbox Code Playgroud)


Ric*_*d W 10

我一直在努力解决这个问题并在圈子里转了一会儿,所以我想我会把我的Rails 4解决方案放在这里.

到目前为止我看到的答案都没有达到我的用例,它们似乎都涉及以某种方式绕过验证,但我希望能够验证其他字段以及密码(如果存在).另外,我没有在我的项目上使用设计,所以我无法使用任何特别的东西.

值得指出的是,这是一个2部分的问题:

步骤1 - 如果密码在控制器中为空,则需要从强参数中删除密码和确认字段:

if myparams[:password].blank?
  myparams.delete(:password)
  myparams.delete(:password_confirmation)
end
Run Code Online (Sandbox Code Playgroud)

第2步 - 您需要更改验证,以便在未输入密码时验证密码.我们不想要的是将它设置为空白,因此我们之前为什么要将它从参数中删除.

在我的情况下,这意味着在我的模型中将其作为验证:

validates :password, :presence => true, :confirmation => true, length: {minimum: 7}, :if => :password
Run Code Online (Sandbox Code Playgroud)

注意:if =>:password - 跳过检查是否未设置密码.

  • 我喜欢这种方法,但我认为将密码验证限制为仅创建方法会更安全,例如 `validates :password, :presence => true, :confirmation => true, length: {minimum: 7}, on: :create`因此仅对 create 方法进行验证 (2认同)

kst*_*tis 6

2017年答案:

Rails 5中,正如 Michael Hartl 的教程所指出的,您在模型中获得以下内容就足够了:

validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
Run Code Online (Sandbox Code Playgroud)

allow_nil: true是这里的关键。这允许用户编辑他/她的信息,而无需更改密码。

此时人们可能会认为这也将允许空用户注册;然而,通过使用自动验证密码是否存在has_secure_password于该方法中可以防止这种情况。create

这是User用于说明目的的演示模型:

validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
Run Code Online (Sandbox Code Playgroud)

不幸的是,我不知道如何使这项工作在设计中发挥作用。干杯。


fl0*_*00r 5

# It smells

def update
  if params[:user][:password].blank?
    params[:user].delete :password
    params[:user].delete :password_confirmation
  end

  if @user.update_attributes(params[:user])
    flash[:success] = "Edit Successful."
    redirect_to @user
  else
    @title = "Edit user"
    render 'edit'
  end
end

# Refactoring

class User < ActiveRecord::Base
  ...
  def update_attributes(params)
    if params[:password].blank?
      params.delete :password
      params.delete :password_confirmation
      super params
    end
  end
  ...
end

def update
  if @user.update_attributes(params[:user])
    flash[:success] = "Edit Successful."
    redirect_to @user
  else
    @title = "Edit user"
    render 'edit'
  end
end

# And little better

class User < ActiveRecord::Base
  ...
  def custom_update_attributes(params)
    if params[:password].blank?
      params.delete :password
      params.delete :password_confirmation
      update_attributes params
    end
  end
  ...
end

def update
  if @user.custom_update_attributes(params[:user])
    flash[:success] = "Edit Successful."
    redirect_to @user
  else
    @title = "Edit user"
    render 'edit'
  end
end
Run Code Online (Sandbox Code Playgroud)