diff --git a/lib/pundit/authorization.rb b/lib/pundit/authorization.rb index 5d02c92c..08b3f115 100644 --- a/lib/pundit/authorization.rb +++ b/lib/pundit/authorization.rb @@ -106,9 +106,9 @@ def policy_scope(scope, policy_scope_class: nil) # # @see https://github.com/varvet/pundit#policies # @param record [Object] the object we're retrieving the policy for - # @return [Object, nil] instance of policy class with query methods + # @return [Object] instance of policy class with query methods def policy(record) - policies[record] ||= pundit.policy!(record) + pundit.policy!(record) end # Retrieves a set of permitted attributes from the policy by instantiating diff --git a/lib/pundit/context.rb b/lib/pundit/context.rb index a3387490..732be8d9 100644 --- a/lib/pundit/context.rb +++ b/lib/pundit/context.rb @@ -27,9 +27,7 @@ def authorize(possibly_namespaced_record, query:, policy_class:) policy = if policy_class policy_class.new(user, record) else - policy_cache.fetch(possibly_namespaced_record) do - policy!(possibly_namespaced_record) - end + policy!(possibly_namespaced_record) end raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query) @@ -86,10 +84,7 @@ def policy_scope!(scope) # @raise [InvalidConstructorError] if the policy constructor called incorrectly # @return [Object, nil] instance of policy class with query methods def policy(record) - policy = policy_finder(record).policy - policy&.new(user, pundit_model(record)) - rescue ArgumentError - raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called" + cached_policy(record, &:policy) end # Retrieves the policy for the given record. Raises if not found. @@ -101,14 +96,24 @@ def policy(record) # @raise [InvalidConstructorError] if the policy constructor called incorrectly # @return [Object] instance of policy class with query methods def policy!(record) - policy = policy_finder(record).policy! - policy.new(user, pundit_model(record)) - rescue ArgumentError - raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called" + cached_policy(record, &:policy!) end private + def cached_policy(record) + policy_cache.fetch(record) do + policy = yield policy_finder(record) + next unless policy + + begin + policy.new(user, pundit_model(record)) + rescue ArgumentError + raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called" + end + end + end + def policy_finder(record) PolicyFinder.new(record) end