Rails5のhas_secure_tokenを使う場合はvalidationをかけてはいけない!

f:id:ihatov08:20160826221248j:plain

rails5から追加されたhas_secure_token

Rails5からtokenを生成するhas_secure_tokenメソッドを使うことができます。

使用例

Schema: User(token:string, auth_token:string)
class User < ActiveRecord::Base
has_secure_token
has_secure_token :auth_token
end
user = User.new
user.save
user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
user.regenerate_token # => true
user.regenerate_auth_token # => true

token設定カラムにpresence valiationを設定してはいけない

上記例だとtokenとauth_tokenカラムにhas_secure_tokenメソッドを適用しています。このカラムにvalidationを適用すると、、、

validates :token, presence: true
user = User.new
user.save!
ActiveRecord::RecordInvalid: バリデーションに失敗しました: tokenを入力してください

valiationエラーが発生します。

なぜかというと、before_createでtokenカラムに値を入れているからです。presence validationを使うと、valiation時点ではnilなので、バリデーションに失敗してしまいます。

      def has_secure_token(attribute = :token)
# Load securerandom only when has_secure_token is used.
require "active_support/core_ext/securerandom"
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
before_create { send("#{attribute}=", self.class.generate_unique_secure_token) unless send("#{attribute}?") }
end

余談:tokenの長さを長くする

has_secure_tokenでは24文字のランダム文字列が生成されます。

1文字=36
2文字=1296
3文字=46656
4文字=1679616
5文字=60466176
6文字=2176782336
7文字=78364164096
8文字=2821109907456
9文字=101559956668416
10文字=3656158440062976
10桁目で3656兆

10桁で3656兆なので、24桁だとかぶることはほぼ無いと思います。
でももっと長くしたい場合は、token生成メソッドはクラスメソッドで定義されているので、クラスメソッドでgenerate_unique_secure_tokenをoverrideできます。

   class << self
def generate_unique_secure_token
SecureRandom.base58(30)
end
end

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です