【问题标题】:(Devise) Password being required on update, even when it was left blank(设计)更新时需要密码,即使它留空
【发布时间】:2013-02-07 22:13:29
【问题描述】:

我的用户模型无法保存,因为密码和密码确认不能为空。这发生在:

  • 在 edit_user_registration 上更新用户并将密码和密码确认留空。这是我第一次注意到的地方
  • 在控制台上,加载对象并调用 save 后立即。

如果 password_required,Devise 将验证密码是否存在?

  validates_presence_of     :password, :if => :password_required?

  def password_required?
    !persisted? || !password.nil? || !password_confirmation.nil?
  end

这是我的 rails 控制台输出:

  Loading development environment (Rails 3.2.11)
  1.9.3p374 :001 > u = User.last
    User Load (1.0ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
   => #<User id: 9, name: "Name", email: "name@example.com", encrypted_password: "$2a$10$oCL2K0nEa8LxaMGuC1oyNOuwIHk8l/IOW.AylGcWTYj3...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 2, current_sign_in_at: "2013-02-06 20:56:14", last_sign_in_at: "2013-02-06 20:52:01", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", confirmation_token: nil, confirmed_at: "2013-02-07 22:04:01", confirmation_sent_at: "2013-02-07 22:03:25", unconfirmed_email: nil, authentication_token: nil, created_at: "2013-02-06 20:52:00", updated_at: "2013-02-07 22:04:31"> 
  1.9.3p374 :002 > u.save
     (0.2ms)  BEGIN
     (0.2ms)  ROLLBACK
   => false 
  1.9.3p374 :003 > u.errors
   => #<ActiveModel::Errors:0x007f832c04f090 @base=#<User id: 9, name: "Name", email: "name@example.com", encrypted_password: "$2a$10$oCL2K0nEa8LxaMGuC1oyNOuwIHk8l/IOW.AylGcWTYj3...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 2, current_sign_in_at: "2013-02-06 20:56:14", last_sign_in_at: "2013-02-06 20:52:01", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", confirmation_token: nil, confirmed_at: "2013-02-07 22:04:01", confirmation_sent_at: "2013-02-07 22:03:25", unconfirmed_email: nil, authentication_token: nil, created_at: "2013-02-06 20:52:00", updated_at: "2013-02-07 22:04:31">, @messages={:password=>["can't be blank"], :password_confirmation=>["can't be blank"]}> 
  1.9.3p374 :004 > !u.persisted? || !u.password.nil? || !u.password_confirmation.nil?
   => false

感谢您的帮助!

【问题讨论】:

  • 你能发布你的整个用户模型吗?这里一定有其他事情发生。您收到 :password_confirmation=>["can't be blank"] 错误很奇怪。您在某处对此进行了验证?
  • 感谢您的帮助!它必须在其他地方,稍后睡个好觉,你的建议很明显。我回答我自己的问题来解释这个问题。再次感谢!

标签: ruby-on-rails ruby devise


【解决方案1】:

感谢@rainkinz,我回到了基础(用户模型)并仔细研究了。我发现我正在导入的一个模块正在添加一个额外的

validates :email, :password, :password_confirmation, presence: true

我可以通过在控制台中运行看到这一点:

User.validators

 ...
 #<ActiveModel::Validations::PresenceValidator:0x007fb80fbcd260
   @attributes=[:email, :password, :password_confirmation],
   @options={}>,
 ...

这与设计中的验证不同,其中包含:

@options={:if=>:password_required?}>,

删除那些解决了问题。感谢您的帮助!

【讨论】:

  • 太棒了。很高兴你明白了。
【解决方案2】:

在您的更新方法中执行此操作。

user = User.find_by_id(params[:id])
    unless user.blank?
      if user.update_attributes(params[:user])
        flash[:notice] = "User updated successfully."
        redirect_to "somwhere"
      else
        render :action => 'edit'
      end
    else
      render :action => 'edit'
    end

如果您不想更新旧密码,请在更新前添加这些行,以便新代码为:

    user = User.find_by_id(params[:id])
        unless user.blank?
          params[:user].delete(:password) if params[:user][:password].blank?
          params[:user].delete(:password_confirmation) if params[:user][:password_confirmation].blank?
if user.update_attributes(params[:user])
            flash[:notice] = "User updated successfully."
            redirect_to "somwhere"
          else
            render :action => 'edit'
          end
        else
          render :action => 'edit'
        end

在 user.rb 模型中写这样的东西

devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :locakable

【讨论】:

  • 没有必要这样做,因为注册正在由 Devise 处理。在注册控制器上调用“resource.update_with_password(resource_params)”(这是当前密码,而不是密码和密码确认),其中params[:password].blank? 在尝试正常的“更新属性(参数,*选项)之前,密码和密码确认都从参数中删除)' 这是模型上发生的事情,因为我能够单独使用控制台复制问题。
  • 另外,使用 find(params[:id]) 代替 find_by_id,它很快就会被弃用(参见 Rails 4),或者更通用的 where(...).first。是的,我的用户模型看起来与此非常相似。
【解决方案3】:

我遇到过类似的问题,但对我有用的解决方案是在完成我想要的操作后再次使用super 调用设计的方法。例如:

def password_required?
  return false if some_check?
  super
end

other answer 的功劳让我大开眼界。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 2014-09-28
    相关资源
    最近更新 更多