コールバックは便利なソリューションですが、必要な複雑なレイヤーを追加しているため、テストが難しくなります。
別のアプローチは、ユーザーの「上」に位置するクラスを作成することです。これが最善の解決策であるとは言いませんが、私が便利だと思ったものです。このクラスは次のクラスを継承していることに注意してくださいUser
。
# user_with_default_password.rb
class UserWithDefaultPassword < User
def initialize(options = {})
random_password = SecureRandom.hex(8)
options[:password] = random_password
# If creating a user with confirmation requirements
options[:password_confirmation] = random_password
# Call User.new(options)
super(options)
end
end
使用法:
user = UserWithDefaultPassword.new() # => user.password = "ajfladfjkf..."
これの利点は、しばしばテストを遅くするコールバックを強制することなく User と UserWithDefaultPassword をテストできることです。
User.new()
また、必要に応じて、代わりに を使用するだけで、デフォルトのパスワードを使用して、または使用せずにユーザーを作成できますUserWithDefaultPassword.new()
。これにより、柔軟性が向上し、テストが改善されます。
更新: 2014-04-21
また、ランダムなパスワードを作成するためのコードなどを、(Rails フレームワークをロードせずに) すばやくテストできる別のクラスに抽出することをお勧めします。以下は、これらの単純なタスクのいくつかを実行するために最近作成したクラスです。
#==================================================
# Generates random/unique strings/tokens/IDs
# See: http://ruby-doc.org/stdlib-2.0.0/libdoc/securerandom/rdoc/SecureRandom.html
# See: http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec-signin_success
#==================================================
class Generator
require "securerandom"
# General-purpose encryption using SHA1 instead of bcrypt; faster but LESS SECURE than bcrypt
# (do not use for extremely sensitive data such as passwords)
def self.encrypt(value)
if value.nil? || value.empty?
""
else
Digest::SHA1.hexdigest(value.to_s)
end
end
# Although a UUID would work as an auto-generated password,
# it just seems more appropriate to make the password a random
# string.
def self.random_password
SecureRandom.urlsafe_base64(32)
end
# Used as a random, unique token
def self.uuid
SecureRandom.uuid
end
# Returns random number as string for admin 2-step authentication
def self.verification_code(length)
value = ""
if length.nil? || length.zero?
length = 6
elsif length > 20
length = 20
end
length.times do |num|
value += SecureRandom.random_number(10).to_s
end
value
end
end
使用法:Generator.random_password # => "abc123..."
大きな利点は、Rails フレームワークをロードせずにランダム パスワードの作成をテストできることです。これにより、ロード時間が 3 ~ 4 秒短縮されます。これは (ほとんどの場合) Rails 4.1 で解決されます。Rails 4.1 では Spring を使用してテスト用にアプリをプリロードしますが、Rails 4.1 を使用していない (または Spring gem を使用している) 場合は、これがより良い解決策です。