简短:我有一个设计模型用户我正在为用户添加一个选项,以便能够在他们的个人资料页面中更改他们的密码,而无需通过“忘记密码”选项。无论如何,这需要一个带有字段的其他表单::old_password, :new_password and :new_password_confirmation
最初不在模型中我必须为它们创建新的单独验证,
表格:
<%= form_for(@user, :url => {:controller => :members, :action => :editpass}, :html => {:method => :post}) do |f| %>
<input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>">
<table class="tables no-border">
<tr>
<%= f.label :old_password, "Old password" %>
</tr>
<tr>
<%= f.password_field :old_password, :autofocus => :true %>
</tr>
<tr>
<%= f.label :new_password, "New password" %>
</tr>
<tr>
<%= f.password_field :new_password %>
</tr>
<tr>
<%= f.label :new_password_confirmation, "Repeat new password" %>
</tr>
<tr>
<%= f.password_field :new_password_confirmation %>
</tr>
<tr>
<input type="submit" value="Change" class="btn" />
</tr>
</table>
</form>
<%= @user.errors.full_messages %>
<% end %>
控制器:
class MembersController < ApplicationController
before_filter :authenticate_user!
skip_before_filter :check_for_main
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
def editpass
current_user.change_password(params[:old_password], params[:new_password])
redirect_to member_path(current_user.id)
end
# User access restriction
def ban
end
def unban
end
end
模型:查看:字段验证:old_password /:new_password ..
class User < ActiveRecord::Base
# Virtual attributes
# _password attributes serve in-profile password change and are not part of the model
attr_accessor :login, :apiid, :vcode, :old_password, :new_password, :new_password_confirmation
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:login]
# Registration show/edit form validation
validates :username, :presence => true,
:length => { :minimum => 6, :maximum => 255 },
:uniqueness => true
validates :apiid, :presence => true,
:numericality => { :only_integer => true },
:acc_api => true,
:on => :create
validates :vcode, :presence => true,
:length => { :minimum => 20, :maximum => 255 },
:on => :create
# In profile password
validates :old_password, :presence => true,
:length => { :minimum => 8, :maximum => 255 },
:if => :password_changed?
validates :new_password, :presence => true,
:length => { :minimum => 8, :maximum => 255 },
:if => :password_changed?,
:confirmation => true
validates :new_password_confirmation,
:presence => true
attr_accessible :login, :username, :group, :apiid, :vcode, :email, :password, :password_confirmation, :remember_me
# Register character belonging to user
after_create :register_characters
# Model association
has_many :apis
has_many :characters
# Allows user to reset password in profile
# for Forgot Password look at Devise
def change_password(oldpass, newpass)
if self.valid_password?(oldpass)
# User is logged out automatically by devise upon
# password change
self.password = newpass
self.save
else
return false
end
end
# Register account characters
def register_characters
require 'nokogiri'
require 'open-uri'
# Fetch account level xml
uri = "https://api.eveonline.com/account/Characters.xml.aspx?keyID=#{self.apiid}&vCode=#{self.vcode}"
xml = Nokogiri::XML(open(uri))
row = xml.xpath("//row")
# Create characters bound to user
row.each do |entry|
# Register new character
character = Character.new(
:charid => entry['characterID'].to_i,
:user_id => self.id,
:name => entry['name'],
:corp => entry['corporationName']
)
character.save
# Register character associated api credentials
api = Api.new(
:user_id => self.id,
:character_id => character.id,
:apiid => self.apiid,
:vcode => self.vcode
)
api.save
character.update_character
end
end
# Check if user is banned before login
def active_for_authentication?
super && self.banned == false
end
# Redefine authentication procedure to allow login with username or email
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login).downcase
where(conditions).where("username = '#{login}' OR email = '#{login}'").first
else
where(conditions).first
end
end
end
答案 0 :(得分:1)
基本上,您的密码验证未达到。
使用change_password
方法,您只需将控制器中的值传递给该方法,并使用它们来设置password
。该模型未设置old_password
和new_password
,因此无法对其进行验证。此外,由于您没有传递password_confirmation
而只是直接在模型中设置密码(self.password = newpass
),因此也未使用password_confirmation
。
正如另一个答案中所提到的,最好使用update_attributes
或Devise文档中推荐的任何内容。希望我的解释能够为您的方法无法正常工作提供一些见解。
如果您想坚持使用change_password
方法,则必须将值传递给属性,以便模型验证它们。尝试这样的事情:
#controller
@user = current_user
if @user.change_password(params[:old_password], params[:new_password], params[:new_password_confirmation])
redirect_to member_path(current_user.id)
else
@errors = @user.errors.full_messages
render 'edit_password_view' # not sure what this action is named
# you now have an array of errors (@errors) that you can render however you see fit in the view
end
#model
def change_password(oldpass, newpass, newpass_conf)
self.password = newpass
self.old_password = oldpass
self.new_password = newpass
self.new_password_confirmation = newpass_conf
return self.save
end
答案 1 :(得分:0)
我认为正确的方法是更新用户属性而不是使用更改密码。也许本指南可以提供帮助:
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-password