Rails state_machine转换导致密码验证错误

时间:2013-12-07 22:03:18

标签: ruby-on-rails passwords ruby-on-rails-plugins railstutorial.org

我一直在关注Michael Hartl的rails教程,并且已经在Signup confirmation处理了他建议的扩展,让用户点击电子邮件链接来激活他们的帐户。为了管理激活,我正在使用state_machine gem,但是当我尝试激活用户帐户时,我收到错误“无法通过以下方式转换状态:激活:挂起(原因:密码太短(最小为6个字符)) )”。 对我来说,似乎state_machine正在实现更新状态字段的数据库操作以某种方式导致与用户记录相关联的验证(可能与has_secure_password方法相关联)被触发并失败。 我在一年前遇到过关于该主题的另一个stackoverflow问题here,但是阅读有关该问题的评论似乎并不是解决方案。

我的用户模型(user.rb)代码如下(它基本上是6.29列表中的教程代码加上状态机的添加)。 [抱歉,无法提供链接,因为stackoverflow不允许我超过2个链接!]

class User < ActiveRecord::Base
  validates :name, presence: true, length: { maximum: 50 } 
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, 
    uniqueness: { case_sensitive: false }
  before_save { email.downcase! }
  validates :password, length: { minimum: 6, maximum: 50 }
  has_secure_password
  before_create :create_remember_token

  state_machine initial: :pending do
    state :pending, value: 0
    state :active, value: 1

    event :activate do
      transition :pending => :active
    end

    event :deactivate do
      transition :active => :pending
    end 
  end

  def initialize
    super()
  end

我的数据库用户表结构是:

create_table "users", force: true do |t|
t.string   "name"
t.string   "email"
t.datetime "created_at"
t.datetime "updated_at"
t.string   "password_digest"
t.string   "remember_token"
t.boolean  "admin",           default: false
t.string   "token"
t.integer  "state"
end

在rails控制台中,state_machine代码似乎正在解释数据库中的值ok,因为我可以获取用户记录以及何时执行user.can_activate?和user.can_deactivate?它正在回归我的期望。但是当我尝试做user.activate时!或user.deactivate!我收到密码太短错误。有关如何解决此问题的任何建议吗?

1 个答案:

答案 0 :(得分:1)

通过更改代码以省去state_machine并直接更新数据库中的state字段,我找到了答案。然后我发现用户记录的所有更新导致密码验证被触发并出现密码长度错误(因此state_machine没有问题)。 如上所述here,解决方案是通过将上面的“验证”行更改为以下内容,如果密码不是要更新的属性之一,则阻止密码验证发生:

validates :password, length: { minimum: 6, maximum: 50 }, :if => :validate_password?
def validate_password?
  password.present? || password_confirmation.present?
end

一旦更改,state_machine功能就可以正常工作。