我正在使用设计进行身份验证,并在设置设计后向users表中添加了一些其他字段。用户只能通过输入电子邮件和密码进行注册,注册后用户可以编辑他的个人资料。为此,我使用过:on =>更新。但是现在当我试图重置密码验证时,触发错误就像名字一样不能空白而等等等等。我正在使用设计和使用注册#edit来重置密码。以下是我的用户模型。
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :dob, :phone, :address, :state, :city, :country, :photo
has_attached_file :photo, :styles => { :small => "150x150>", :medium => "300x300>", :large => "500x500>" }
has_many :blogs, :dependent => :destroy
has_many :comments, :dependent => :destroy
has_many :followers, :through => :blogs
has_many :followings, :class_name => 'Follower', :foreign_key => 'user_id'
has_many :following_blogs, :through => :followings, :source => :blog
has_many :blog_followers, :through => :followers, :source => :user
phone_regex = /^[0-9]+$/
validates_attachment_size :photo, :less_than => 3.megabytes
validates_attachment_content_type :photo, :content_type => ['image/jpeg','image/png','image/jpg','image/gif']
validates :name, :presence => true, :on => :update
validates :dob, :presence => true, :on => :update
validates :phone, :format => { :with => phone_regex }, :length => { :is => 10 }, :on => :update
validates :address, :presence => true, :on => :update
validates :state, :presence => true,:length => { :maximum => 30 }, :on => :update
validates :city, :presence => true, :length => { :maximum => 30 }, :on => :update
validates :country, :presence => true, :length => { :maximum => 30 }, :on => :update
end
答案 0 :(得分:2)
基于Sam Stickland回答......
尽管保存update_attribute(:encrypted_password, encrypted_password)
我认为使用save(validate: false)
进行保存更好更明确。
此外,您可以避免扩展更新控制器操作实现重置密码,如
def reset_password(new_password, new_password_confirmation)
byebug
if new_password.present?
self.password = new_password
self.password_confirmation = new_password_confirmation
if valid?
save
elsif errors.messages.select { |k,_v| k[/password/] }.empty?
errors.clear
save(validate: false)
else
false
end
else
errors.add(:password, :blank)
false
end
end
答案 1 :(得分:1)
我有同样的问题。这是我找到的解决方案。
它在设计内部挖掘了一点,所以我建议你测试一下。我发现在尝试实现这一点时我打破了很多东西(包括不需要匹配的密码确认,或者更改密码!)
以下是我的测试套件片段,用于检查密码重置:https://gist.github.com/samstickland/9744ee29d0028162a7a8
问题是设计使用验证来检查密码匹配,它是有效密码(即不是太短)并且密码令牌有效。这意味着一旦你停止使用有效?您必须寻找特定错误消息的方法。
首先,您必须覆盖用户模型中的reset_password方法。如果错误消息不包含任何“密码”错误,则此新方法将直接写入加密密码(作为password =方法的一部分创建)。
最初的设计实现可以在这里找到:https://github.com/plataformatec/devise/blob/18a8260535e5469d05ace375b3db3bcace6755c1/lib/devise/models/recoverable.rb#L39(注意:我没有实现after_password_reset,因为它已被弃用)
def reset_password(new_password, new_password_confirmation)
self.password = new_password
self.password_confirmation = new_password_confirmation
if valid?
save
elsif errors.messages.select { |k,v| k[/password/] }.empty?
# No password errors, so we write the password directly to the DB
update_attribute(:encrypted_password, encrypted_password)
true
else
false
end
end
接下来,您必须实现自己的PasswordsController,因为更新方法还将检查错误是否为空。将其更改为仅查找密码错误。这是我的。
我还必须更改为response_with redirect_to,以便在重置无效模型上的密码时使重定向工作。我真的不明白为什么这是必要的。
#
# This is identical to the original devise password controller except
# that it allows resetting of passwords in invalid models (i.e.
# confirmed users without a valid profile
#
class Users::PasswordsController < Devise::PasswordsController
# GET /resource/password/new
# def new
# super
# end
# POST /resource/password
# def create
# super
# end
# GET /resource/password/edit?reset_password_token=abcdef
# def edit
# super
# end
# PUT /resource/password
def update
self.resource = resource_class.reset_password_by_token(resource_params)
yield resource if block_given?
# Was:
# if resource.errors.empty?
# It's been changed to allow resetting passwords of invalid models
if resource.errors.messages.select { |k,v| k[/password/] }.empty?
resource.unlock_access! if unlockable?(resource)
if Devise.sign_in_after_reset_password
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message(:notice, flash_message) if is_flashing_format?
sign_in(resource_name, resource)
# Was:
# respond_with resource, location: after_resetting_password_path_for(resource)
# but this didn't seem to redirect User's with invalid attributes so I've changed
# it to a redirect
redirect_to after_resetting_password_path_for(resource)
else
set_flash_message(:notice, :updated_not_active) if is_flashing_format?
respond_with resource, location: new_session_path(resource_name)
end
else
respond_with resource
end
end
# protected
# def after_resetting_password_path_for(resource)
# super(resource)
# end
# The path used after sending reset password instructions
# def after_sending_reset_password_instructions_path_for(resource_name)
# super(resource_name)
# end
end
答案 2 :(得分:0)
实际上,问题是您正在使用可验证的设计模块。它将自动验证放在电子邮件和密码甚至更新。更好的选择是在电子邮件和电子邮件上添加自己的验证。创建密码并在模型中进行这些更改或完全删除它。
User Model
def email_required?
false
end
def password_changed?
false
end
希望这会有所帮助。
答案 3 :(得分:0)
我不确定是否有一个简单的答案。 我相信以某种方式迫使用户在注册后更新这些字段(如帐户“激活”)是个好主意。从技术上讲,如果您已经定义了这些验证,则用户 无效
。不过,我猜您可以通过以下解决方法来避免验证:
在验证中添加:unless
选项(请参阅this):
validates :name, :presence => true, :on => :update, :unless => :resetting_password?
然后定义一个resetting_password?
方法,并在你这样做时返回true。您可以通过在devise的注册控制器中设置变量来完成此操作。我认为使用attr_accessor
就足够了。
可能有更好的解决方案,但这就是我现在能想到的。