现在我意识到这个话题已经被多次讨论过了。但是,似乎没有一种解决方案只有在数据库中的密码为空时才能使当前密码字段免除。
我目前在我的用户模型中需要密码,如:
def password_required?
(authentications.empty? || !password.blank?) && super
end
然后我将更新功能复制到我的注册控制器中:
def update
if resource.update_with_password(params[resource_name])
set_flash_message :notice, :updated
sign_in resource_name, resource, :bypass => true
redirect_to after_update_path_for(resource)
else
clean_up_passwords(resource)
render_with_scope :edit
end
end
我只是不知道在编辑空白密码时如何确保设计不需要密码,我是否还需要从视图中删除current_password字段并执行此操作?
<% if current_user.password_required? %>
<p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></p>
<% end %>
<p><%= f.submit "Update" %></p>
任何建议对此都很好,因为我确信我忽略了一些东西,但我仍然是Rails的新手。谢谢!
答案 0 :(得分:8)
好的,所以我终于想出来了!
将以下内容添加到您的类RegistrationsController&lt;设计:: RegistrationsController
def update
if resource.update_with_password(params[resource_name])
set_flash_message :notice, :updated
sign_in resource_name, resource, :bypass => true
redirect_to after_update_path_for(resource)
else
clean_up_passwords(resource)
render_with_scope :edit
end
end
然后是您的用户模型:
def update_with_password(params={})
current_password = params.delete(:current_password) if !params[:current_password].blank?
if params[:password].blank?
params.delete(:password)
params.delete(:password_confirmation) if params[:password_confirmation].blank?
end
result = if has_no_password? || valid_password?(current_password)
update_attributes(params)
else
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
self.attributes = params
false
end
clean_up_passwords
result
end
def has_no_password?
self.encrypted_password.blank?
end
我唯一有点困惑的是在编辑视图中:
<% if !current_user.has_no_password? %>
我把它包裹起来,如果,我原本以为它会是:
<% if current_user.has_no_password? %>
如果有人能看到任何改进我的代码或更有效的方式让我知道!
答案 1 :(得分:3)
要求当前密码字段的另一个非常小的变化:我的目标是永远不需要当前密码,除非他们更新他们的密码。对于oauth'ed帐户,我在视图中检查了facebook id,并且根本不显示密码字段。
在注册控制器中:
Users::RegistrationsController < Devise::RegistrationsController
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
if resource.update_with_password(params[resource_name])
set_flash_message :notice, :updated if is_navigational_format?
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords(resource)
respond_with_navigational(resource){ render_with_scope :edit }
end
end
在User.rb中,我使用update_with_password,然后仅当用户在视图的密码字段中输入了内容时才调用verify_password_and_update。否则,我清除当前的密码参数并调用update_without_password(此方法现在内置于设计中):
#to remove the current password check if updating a profile originally gotten via oauth (fb, twitter)
def update_with_password(params={})
if params[:password].blank?
params.delete(:current_password)
self.update_without_password(params)
else
self.verify_password_and_update(params)
end
end
def update_without_password(params={})
params.delete(:password)
params.delete(:password_confirmation)
result = update_attributes(params)
clean_up_passwords
result
end
def verify_password_and_update(params)
#devises' update_with_password
# https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb
current_password = params.delete(:current_password)
if params[:password].blank?
params.delete(:password)
params.delete(:password_confirmation) if params[:password_confirmation].blank?
end
result = if valid_password?(current_password)
update_attributes(params)
else
self.attributes = params
self.valid?
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false
end
clean_up_passwords
result
end