背景
パスワードリセットの為に一意のtokenを生成して、
http://example.com/password_reset/#{token}
みたいなURLにアクセスしてパスワードをリセットするというのをやりたかった。
user_info.rb
class UserInfo < ActiveRecord::Base
belongs_to :user
# <!--省略 -->
validates :token, uniqueness: true
end
tokenは一意に定まるので、model層でのバリデーションは上記の様にやれば良いと踏んで実装したが、
今まで通っていたはずの別のテストが、通らなくなった。
原因
tokenは、ユーザーがパスワードをリセットしたいと望んだ時に初めて生成されるものなので、初期状態はnil
である。
つまり、nil
の状態を持ったユーザーがたくさん作成されると、nil
というtokenの値を持ったデータが複数個作られるため、一意に定まってないじゃん!とActiveRecord
が誤作動してしまうというのが原因(だと思う)。
mysqlではデフォルトでnil
は無視されるので、どんなにnil
の値を持ったユーザーがいても大丈夫なのだけれど、ActiveRecord
ではうまくいかなかった。
対処法
user_info.rb
class UserInfo < ActiveRecord::Base
belongs_to :user
# <!--省略 -->
validates :token, uniqueness: true, allow_nil: true
end
allow_nil: true
を付け足して、明示的に教えてあげたらうまくいった。