我有一个自定义验证程序,用于检查用户是否输入了正确的SMS代码。当用户输入错误的代码时,我需要记录失败的尝试并将其重试限制为每个代码3个。
我创建了以下验证器,但该字段没有递增。
def token_match
if token != User.find(user_id).verification_token
User.find(user_id).increment!(:verification_fails)
errors.add(:sms_code, "does not match")
end
end
问题是我在添加错误后立即回滚前一个语句。如果我注释掉errors.add行,那么增量就会起作用,但是没有执行更高级别的验证。
答案 0 :(得分:0)
您可以在验证程序中使用#update_columns
。它直接写入db。
u = User.find(user_id)
u.update_columns(verification_fails: u.verification_fails + 1)
这对我有用。但如果由于某种原因它不能为你工作,也许你可以尝试在一个新的线程中运行它,这会创建一个新的数据库连接:
Thread.new do
num = User.find(user_id).verification_fails
ActiveRecord::Base.connection_pool.with_connection { |con| con.exec_query("UPDATE users SET verification_fails = #{num} WHERE id = #{user_id}") }
end.join
答案 1 :(得分:0)
将自定义验证程序更改为:
def token_match
if token != User.find(user_id).verification_token
errors.add(:sms_code, "does not match")
end
end
并在模型中添加after_validation
回调,如下所示:
after_validation: increase_fails_count
def increase_fails_count
unless self.errors[:sms_code].empty?
user = User.find_by(:id => user_id)
user.increment!(:verification_fails)
user.save
end
end