Pundit: RSpec + Pundit; Undefined method all? and none?

Created on 5 Apr 2014  路  17Comments  路  Source: varvet/pundit

This may be something really simple, but I was unable to find any answer after extensive googling.

I'm trying to run the following RSpec test:

require "spec_helper"

describe ReportPolicy do
  subject { ReportPolicy.new(user, report) }

  let(:user)    { FactoryGirl.create(:user) }
  let(:report)  { FactoryGirl.create(:report, organization_id: user.organization_id) }

  context "for a user" do
    it { should       permit(:show) }
    it { should_not   permit(:edit) }
  end  
end

It is failing with the errors:

1) ReportPolicy for a user should permit :show
     Failure/Error: it { should       permit(:show) }
     NoMethodError:
       undefined method `all?' for nil:NilClass
     # ./spec/policies/report_policy_spec.rb:10:in `block (3 levels) in <top (required)>'
2) ReportPolicy for a user should not permit :edit
     Failure/Error: it { should_not   permit(:edit) }
     NoMethodError:
       undefined method `none?' for nil:NilClass
     # ./spec/policies/report_policy_spec.rb:11:in `block (3 levels) in <top (required)>'

Can anyone explain what is going on here?

Most helpful comment

Pundit includes a mini-DSL for writing expressive tests for your policies in RSpec. Require pundit/rspec in your spec_helper.rb:

require "pundit/rspec" # Remove this line in your spec_helper.rb

All 17 comments

Please post a stack trace.

Updated the original. (not a whole lot of information to troubleshoot with) Thanks.

Run RSpec with -b to get a full stack trace.

On Saturday, April 5, 2014, Trey Keifer [email protected] wrote:

Updated the original. (not a whole lot of information in the errors)

Reply to this email directly or view it on GitHubhttps://github.com/elabs/pundit/issues/130#issuecomment-39646836
.

Interesting. I didn't know about that option. Here you go...

1) ReportPolicy for a user should not permit :edit
     Failure/Error: it { should_not   permit(:edit) }
     NoMethodError:
       undefined method `none?' for nil:NilClass
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/pundit-0.2.2/lib/pundit/rspec.rb:12:in `block (2 levels) in <module:Matchers>'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-expectations-2.14.5/lib/rspec/matchers/extensions/instance_eval_with_args.rb:11:in `instance_exec'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-expectations-2.14.5/lib/rspec/matchers/extensions/instance_eval_with_args.rb:11:in `instance_eval_with_args'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-expectations-2.14.5/lib/rspec/matchers/matcher.rb:222:in `does_not_match?'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-expectations-2.14.5/lib/rspec/expectations/handler.rb:49:in `handle_matcher'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/memoized_helpers.rb:82:in `should_not'
     # ./spec/policies/report_policy_spec.rb:11:in `block (3 levels) in <top (required)>'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:114:in `instance_eval'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:114:in `block in run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:179:in `call'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:179:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_exec'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_eval_with_args'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:247:in `instance_eval_with_args'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:106:in `block (2 levels) in run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:108:in `call'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:108:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:446:in `run_hook'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:340:in `run_around_each_hooks'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:256:in `with_around_each_hooks'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:111:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:390:in `block in run_examples'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:386:in `map'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:386:in `run_examples'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:371:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `block in run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `map'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `block (2 levels) in run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `map'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `block in run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/reporter.rb:58:in `report'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:25:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:80:in `run'
     # /Users/[redacted]/.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:17:in `block in autorun'

I got the same error in a similar test constellation. Any ideas?
Here is the full stack trace:

$ rspec -b ./spec/policies/recurrence_policy_spec.rb
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}

RecurrencePolicy
  for a related user
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
    should permit :show (FAILED - 1)

Failures:

  1) RecurrencePolicy for a related user should permit :show
     Failure/Error: it { should     permit(:show)    }
     NoMethodError:
       undefined method `all?' for nil:NilClass
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/pundit-0.2.3/lib/pundit/rspec.rb:8:in `block (2 levels) in <module:Matchers>'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-expectations-2.14.5/lib/rspec/matchers/extensions/instance_eval_with_args.rb:11:in `instance_exec'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-expectations-2.14.5/lib/rspec/matchers/extensions/instance_eval_with_args.rb:11:in `instance_eval_with_args'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-expectations-2.14.5/lib/rspec/matchers/matcher.rb:61:in `matches?'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-expectations-2.14.5/lib/rspec/expectations/handler.rb:24:in `handle_matcher'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/memoized_helpers.rb:68:in `should'
     # ./spec/policies/recurrence_policy_spec.rb:19:in `block (3 levels) in <top (required)>'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:114:in `instance_eval'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:114:in `block in run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:254:in `with_around_each_hooks'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:111:in `run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:390:in `block in run_examples'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:386:in `map'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:386:in `run_examples'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:371:in `run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `block in run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `map'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `block (2 levels) in run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `map'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `block in run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/reporter.rb:58:in `report'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:25:in `run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:80:in `run'
     # /home/user/.rvm/gems/ruby-1.9.3-p484/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:17:in `block in autorun'

Top 1 slowest examples (0.50138 seconds, 100.0% of total time):
  RecurrencePolicy for a related user should permit :show
    0.50138 seconds ./spec/policies/recurrence_policy_spec.rb:19

Finished in 0.50194 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/policies/recurrence_policy_spec.rb:19 # RecurrencePolicy for a related user should permit :show

You're not using the matchers the right way. I admit they're kinda weird. Essentially you need to wrap them in a permissions block, as demonstrated in the README. https://github.com/elabs/pundit#policy-specs

Sorry, for asking again. I agree that the syntax showed at https://github.com/elabs/pundit#policy-specs works fine!

But I was asking concerning the alternatively mentioned approach "scoping to user context":

An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this
excellent post.

Doing like this:

require 'spec_helper'

describe RecurrencePolicy do
  let(:user) { FactoryGirl.create(:user) }
  let(:recurrence) { FactoryGirl.create(:recurrence) }

  subject { RecurrencePolicy.new(user, recurrence) }

  context "for a user" do
    context "not associated to the related group" do
      let(:membership) { nil }

      it { should_not permit(:show)    }
      it { should_not permit(:edit)    }
      it { should_not permit(:update)  }
      it { should_not permit(:destroy) }
    end
  end
end

fails with above error message! Could this problem concern the usage of rspec version 2 vs. 3?

Are you by chance including both the permit matchers from pundit and the one from the blog? In this case, you should rename the one from the blog (or not include the one from Pundit, if you don't use it).

To clarify, the article suggest a matcher like this:

# spec/support/matchers/pundit_matcher.rb
RSpec::Matchers.define :permit do |action|
  match do |policy|
    policy.public_send("#{action}?")
  end

  failure_message_for_should do |policy|
    "#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
  end

  failure_message_for_should_not do |policy|
    "#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
  end
end

You'll need to include it yourself in the app, and not require the one pundit ships, or rename the custom one if you want to use both.

ok, my fault. Obviously I didn't read well, because I didn't added an extra/new "matcher".
Now I saw and read the link to the thunderbolt blog.

Thanks for the hint.

No problem :)

ok, the "strategy"

  • via renaming the custom matcher works fine,
  • but how not to "include own the Pundit matcher"?

By the way ... the rspec section of the README doesn't show any example concerning the index action aka "policy_scope". Do you like a PR on that?

Pundit includes a mini-DSL for writing expressive tests for your policies in RSpec. Require pundit/rspec in your spec_helper.rb:

require "pundit/rspec" # Remove this line in your spec_helper.rb

A short example on specs for policy_scope would be be a nice PR! If you need any help, just open the PR and we'll continue the discussion there.

thanks for this thread - just saved me a ton of time

I wish I had found this before I ended up renaming the custom matcher to fix the issue. Thanks for the policy_scope spec example!

failure_message_for_should and failure_message_for_should_not are deprecated. Use failure_message and failure_message_when_negated instead.

Was this page helpful?
0 / 5 - 0 ratings