Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix PolicyFinder when given an array with policy class override #475

Merged
merged 1 commit into from May 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 15 additions & 14 deletions lib/pundit/policy_finder.rb
Expand Up @@ -36,7 +36,7 @@ def scope
# policy.update? #=> false
#
def policy
klass = find
klass = find(object)
klass = klass.constantize if klass.is_a?(String)
klass
rescue NameError
Expand All @@ -48,15 +48,15 @@ def policy
#
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}`"
scope or raise NotDefinedError, "unable to find scope `#{find(object)}::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}`"
policy or raise NotDefinedError, "unable to find policy `#{find(object)}` for `#{object.inspect}`"
end

# @return [String] the name of the key this object would have in a params hash
Expand All @@ -73,19 +73,20 @@ def param_key

private

def find
if object.nil?
def find(subject)
if subject.nil?
nil
elsif object.respond_to?(:policy_class)
object.policy_class
elsif object.class.respond_to?(:policy_class)
object.class.policy_class
elsif subject.is_a?(Array)
modules = subject.dup
last = modules.pop
context = modules.map { |x| find_class_name(x) }.join("::")
[context, find(last)].join("::")
elsif subject.respond_to?(:policy_class)
subject.policy_class
elsif subject.class.respond_to?(:policy_class)
subject.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 = find_class_name(subject)
"#{klass}#{SUFFIX}"
end
end
Expand Down
14 changes: 14 additions & 0 deletions spec/pundit_spec.rb
Expand Up @@ -134,6 +134,13 @@
expect(policy.post).to eq [:project, post]
end

it "returns an instantiated policy given an array of a symbol and a model instance with policy_class override" do
policy = Pundit.policy(user, [:project, customer_post])
expect(policy.class).to eq Project::PostPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, customer_post]
end

it "returns an instantiated policy given an array of a symbol and an active model instance" do
policy = Pundit.policy(user, [:project, comment])
expect(policy.class).to eq Project::CommentPolicy
Expand All @@ -155,6 +162,13 @@
expect(policy.post).to eq [:project, Comment]
end

it "returns an instantiated policy given an array of a symbol and a class with policy_class override" do
policy = Pundit.policy(user, [:project, Customer::Post])
expect(policy.class).to eq Project::PostPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, Customer::Post]
end

it "returns correct policy class for an array of a multi-word symbols" do
policy = Pundit.policy(user, [:project_one_two_three, :criteria_four_five_six])
expect(policy.class).to eq ProjectOneTwoThree::CriteriaFourFiveSixPolicy
Expand Down
6 changes: 5 additions & 1 deletion spec/spec_helper.rb
Expand Up @@ -77,9 +77,13 @@ def model_name
OpenStruct.new(param_key: "customer_post")
end

def policy_class
def self.policy_class
PostPolicy
end

def policy_class
self.class.policy_class
end
end
end

Expand Down