mirror of
https://github.com/varvet/pundit.git
synced 2022-11-09 12:30:11 -05:00
110 lines
2.8 KiB
Ruby
110 lines
2.8 KiB
Ruby
module Pundit
|
|
# Finds policy and scope classes for given object.
|
|
# @api public
|
|
# @example
|
|
# user = User.find(params[:id])
|
|
# finder = PolicyFinder.new(user)
|
|
# finder.policy #=> UserPolicy
|
|
# finder.scope #=> UserPolicy::Scope
|
|
#
|
|
class PolicyFinder
|
|
attr_reader :object
|
|
|
|
# @param object [any]
|
|
#
|
|
def initialize(object)
|
|
@object = object
|
|
end
|
|
|
|
# @return [nil, Scope{#resolve}]
|
|
# @see https://github.com/elabs/pundit#scopes
|
|
# @example
|
|
# scope = finder.scope #=> UserPolicy::Scope
|
|
# scope.resolve #=> <#ActiveRecord::Relation ...>
|
|
#
|
|
def scope
|
|
policy::Scope if policy
|
|
rescue NameError
|
|
nil
|
|
end
|
|
|
|
# @return [nil, Class] policy class with query methods
|
|
# @see https://github.com/elabs/pundit#policies
|
|
# @example
|
|
# policy = finder.policy #=> UserPolicy
|
|
# policy.show? #=> true
|
|
# policy.update? #=> false
|
|
#
|
|
def policy
|
|
klass = find
|
|
klass = klass.constantize if klass.is_a?(String)
|
|
klass
|
|
rescue NameError
|
|
nil
|
|
end
|
|
|
|
# @return [Scope{#resolve}]
|
|
# @raise [NotDefinedError] if scope could not be determined
|
|
#
|
|
def scope!
|
|
raise NotDefinedError, "unable to find policy scope of nil" if object.nil?
|
|
scope or raise NotDefinedError, "unable to find scope `#{find}::Scope` for `#{object.inspect}`"
|
|
end
|
|
|
|
# @return [Class] policy class with query methods
|
|
# @raise [NotDefinedError] if policy could not be determined
|
|
#
|
|
def policy!
|
|
raise NotDefinedError, "unable to find policy of nil" if object.nil?
|
|
policy or raise NotDefinedError, "unable to find policy `#{find}` for `#{object.inspect}`"
|
|
end
|
|
|
|
# @return [String] the name of the key this object would have in a params hash
|
|
#
|
|
def param_key
|
|
if object.respond_to?(:model_name)
|
|
object.model_name.param_key.to_s
|
|
elsif object.is_a?(Class)
|
|
object.to_s.demodulize.underscore
|
|
else
|
|
object.class.to_s.demodulize.underscore
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
# @return [String] policy class name
|
|
# @api public
|
|
#
|
|
def find
|
|
if object.nil?
|
|
nil
|
|
elsif object.respond_to?(:policy_class)
|
|
object.policy_class
|
|
elsif object.class.respond_to?(:policy_class)
|
|
object.class.policy_class
|
|
else
|
|
klass = if object.is_a?(Array)
|
|
object.map { |x| find_class_name(x) }.join('::')
|
|
else
|
|
find_class_name(object)
|
|
end
|
|
"#{klass}#{SUFFIX}"
|
|
end
|
|
end
|
|
|
|
def find_class_name(subject)
|
|
if subject.respond_to?(:model_name)
|
|
subject.model_name
|
|
elsif subject.class.respond_to?(:model_name)
|
|
subject.class.model_name
|
|
elsif subject.is_a?(Class)
|
|
subject
|
|
elsif subject.is_a?(Symbol)
|
|
subject.to_s.camelize
|
|
else
|
|
subject.class
|
|
end
|
|
end
|
|
end
|
|
end
|