我的用户模型有一个名为“points”的属性,当我尝试在另一个模型控制器(递减点)中更新它时,该属性将不会保存(即使在将其添加到attr_accessible之后)。
我的Venture Controller代码中的方法:
def upvote
@venture = Venture.find(params[:id])
if current_user.points < UPVOTE_AMOUNT
flash[:error] = "Not enough points!"
else
flash[:success] = "Vote submitted!"
current_user.vote_for(@venture)
decremented = current_user.points - UPVOTE_AMOUNT
current_user.points = decremented
current_user.save
redirect_to :back
end
我甚至尝试过使用update_attributes方法,但无济于事。
我添加了一个快速的小测试,看看它是否正在保存:
if current_user.save
flash[:success] = "Yay"
else
flash[:error] = "No"
end
并返回错误。
current_user来自我的Sessions助手:
def current_user
@current_user ||= user_from_remember_token
end
提前致谢。
我的用户模型:
class User < ActiveRecord::Base
attr_accessor :password, :points
attr_accessible :name, :email, :password, :password_confirmation, :points
STARTING_POINTS = 50
acts_as_voter
has_karma :ventures
has_many :ventures, :dependent => :destroy
email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
after_initialize :initialize_points
def has_password?(submitted_password)
password_digest == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
private
def initialize_points
self.points = STARTING_POINTS
end
def encrypt_password
self.salt = make_salt if new_record?
self.password_digest = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
这是我打印后得到的&lt;%= debug current_user%&gt;
--- !ruby/object:User
attributes:
id: 1
name: Test User
email: a@s.com
created_at: 2011-08-27 21:03:01.391918
updated_at: 2011-08-27 21:03:01.418370
password_digest: 40d5ed415df384adaa5182a5fe59964625f9e65a688bb3cc9e30b4eef2a0614b
salt: ac7a332f5d63bc6ad0f61ceacb66bc154e1cad1164fcaed6189d8cea2b55ffe4
admin: t
points: 50
longitude_user:
latitude_user:
attributes_cache: {}
changed_attributes: {}
destroyed: false
errors: !omap []
marked_for_destruction: false
new_record: false
points: 50
previously_changed: {}
readonly: false
答案 0 :(得分:2)
您需要在用户保存时随时出现用户密码。当提交upvote时,密码不存在,因此验证没有通过。
答案 1 :(得分:1)
这表明某种验证失败了。避免这种情况的一种简单方法是使用update_attribute
。这将更新单个属性并保存而不运行验证。
所以改为写
current_user.update_attribute :points, current_user.points - UPVOTE_AMOUNT
这应该有用。
这并不能解决为什么保存现有用户可能会失败的问题,因此您仍需要检查验证和before_save
操作。
希望这有帮助。
哈。确实。 update_attribute
会跳过验证,但不会跳过before_save
。
因此,如果before_save
是问题所在,您只想在密码更改时触发,因此您可以执行类似
def encrypt_password
self.salt = make_salt if new_record?
self.password_digest = encrypt(password) if self.password_changed?
end
但这只有在password
是模型的实际属性时才有效,这似乎不太可能。为什么要以明文形式存储哈希(出于安全原因)和密码。所以...我想你只有一个password_digest
字段,然后它应该变成类似:
def encrypt_password
self.salt = make_salt if new_record?
self.password_digest = encrypt(password) if password.present?
end
仅在提供密码时,尝试重新创建摘要。