用户属性不会保存

时间:2011-08-27 23:41:23

标签: ruby-on-rails ruby model controller save

我的用户模型有一个名为“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

2 个答案:

答案 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

仅在提供密码时,尝试重新创建摘要。