A PolicyResult
class to help collect the status
and message
from a policy check
class PolicyResult
attr_reader :message, :status
def initialize(params)
@status = params.fetch(:status, false)
@message = params.fetch(:message, :no_message)
end
end
Then a refactor of a policy to return the status and optionally call a block with the full result
Usage:
class User < ActiveRecord::Base
...
def verifiable?(&block)
VerificationEligibilityPolicy.call &block
end
end
current_user.verifiable? #=> true/false
current_user.verifiable? do |result|
return nil if result.status
redirect_to root_path, error: result.message
end
Which would have a refactor like the following:
class VerificationEligibilityPolicy
MAX_ATTEMPTS = 2
def self.call(params, &block)
policy = new(params)
result = policy.eligible?
block.call result if block
result.status
end
def initialize(params)
@user = params.fetch(:user)
@attempts = @user.attempts.recent
end
##
# checks that a user has not reached
# max verification attempts or
# that the user has waited past
# the retry time window: 1.day
def eligible?
if !@user.identified_person?
PolicyResult.new({message: "Create Identity"})
elsif @attempts.count < MAX_ATTEMPTS
next_time = @attempts.last.created_at + wait_time
PolicyResult.new({message: "Please wait #{next_time}"})
else
PolicyResult.new({staus: true})
end
end
private
def wait_time
1.day
end
end
Also potentially only run the
block
if the status isfalse
?