Pundit: NoMethodError: undefined method 'find_all' for nil:NilClass when running rspec ./spec/policies/

Created on 12 May 2017  路  4Comments  路  Source: varvet/pundit

I'm running into an issue when I try to run the specs for all the policies. The specs all pass when I run each policy spec individually, but when I try to run them all together, the specs from the first file all pass, but I get the following error for each permit spec after.

1) BrandPolicy for an admin .permission should permit :show
     Failure/Error: it { should permit(:show) }

     NoMethodError:
       undefined method `find_all' for nil:NilClass
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/pundit-1.1.0/lib/pundit/rspec.rb:10:in `block (2 levels) in <module:Matchers>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/matchers/dsl.rb:70:in `block (2 levels) in match'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-support-3.5.0/lib/rspec/support.rb:103:in `with_failure_notifier'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/matchers/dsl.rb:68:in `block in match'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/expectations/handler.rb:50:in `block in handle_matcher'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/expectations/handler.rb:27:in `with_matcher'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/memoized_helpers.rb:81:in `should'
     # ./spec/policies/brand_policy_spec.rb:23:in `block (4 levels) in <top (required)>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `block in run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `block in with_around_and_singleton_context_hooks'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `block in with_around_example_hooks'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `block in run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:604:in `block in run_around_example_hooks_for'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-rails-3.5.2/lib/rspec/rails/adapters.rb:127:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
     # ./spec/rails_helper.rb:44:in `block (2 levels) in <top (required)>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
     # ./spec/spec_helper.rb:75:in `block (2 levels) in <top (required)>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:607:in `run_around_example_hooks_for'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `with_around_example_hooks'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `with_around_and_singleton_context_hooks'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:251:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:627:in `block in run_examples'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `map'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `run_examples'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:589:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (3 levels) in run_specs'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `map'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (2 levels) in run_specs'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1835:in `with_suite_hooks'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/reporter.rb:77:in `report'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:111:in `run_specs'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:87:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/exe/rspec:4:in `<top (required)>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/rspec:22:in `load'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/rspec:22:in `<main>'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/ruby_executable_hooks:15:in `eval'
     # /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/ruby_executable_hooks:15:in `<main>'

Here is a sample of one of my policy specs. They all follow the same general format.

require 'rails_helper'

RSpec.describe BrandPolicy, type: :policy do

  subject { BrandPolicy.new(user, Brand) }

  let!(:admin_user) { create(:employee).user }
  let!(:tutor_user) { create(:tutor).user }
  let!(:parent_user) { create(:parent).user }
  let!(:student_user) { create(:student, parent: parent_user.parent).user }
  let!(:brand) { create(:brand) }

  context 'for an admin' do
    let(:user) { admin_user }

    describe '.scope' do
      it 'returns all brands' do
        expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
      end
    end

    describe '.permission' do
      it { should permit(:show) }
      it { should permit(:update) }
      it { should permit(:create) }
      it { should permit(:destroy) }
    end
  end

  context 'for a tutor' do
    let(:user) { tutor_user }

    describe '.scope' do
      it 'returns all brands' do
        expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
      end
    end

    describe '.permission' do
      it { should permit(:show) }
      it { should_not permit(:update) }
      it { should_not permit(:create) }
      it { should_not permit(:destroy) }
    end
  end

  context 'for a parent' do
    let(:user) { parent_user }

    describe '.scope' do
      it 'returns all brands' do
        expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
      end
    end

    describe '.permission' do
      it { should permit(:show) }
      it { should_not permit(:update) }
      it { should_not permit(:create) }
      it { should_not permit(:destroy) }
    end
  end

  context 'for a student' do
    let(:user) { student_user }

    describe '.scope' do
      it 'returns all brands' do
        expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
      end
    end

    describe '.permission' do
      it { should permit(:show) }
      it { should_not permit(:update) }
      it { should_not permit(:create) }
      it { should_not permit(:destroy) }
    end
  end
end

edit: The specs from the first file all pass because it doesn't have any permit tests (lol).

Most helpful comment

I had a similar error using this suggested custom matcher. After reading up on it, I renamed the :permit action in the code block to :authorize, like so, and now it works like a dream!

RSpec::Matchers.define :authorize do |action|
  match do |policy|
    policy.public_send("#{action}?")
  end

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

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

Then I just required the default pundit/rspec and that custom pundit_matcher in my rails_helper.rb. Now it works great!

The issue is apparently a naming conflict between the custom permit matcher defined here and the built-in Pundit rspec method permit, as discussed in this post... https://github.com/elabs/pundit/issues/130. Once the custom pundit_matcher method is renamed to something else (like authorize) it works great for me. Just in case it's helpful...

All 4 comments

Here is the pundit_matcher.rb file I'm using. It's the same custom matcher that's recommended in the guides.

RSpec::Matchers.define :permit do |action|
  match do |policy|
    policy.public_send("#{action}?")
  end

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

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

I found this Pundit-Matchers gem and that fixed the issue.

I had a similar error using this suggested custom matcher. After reading up on it, I renamed the :permit action in the code block to :authorize, like so, and now it works like a dream!

RSpec::Matchers.define :authorize do |action|
  match do |policy|
    policy.public_send("#{action}?")
  end

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

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

Then I just required the default pundit/rspec and that custom pundit_matcher in my rails_helper.rb. Now it works great!

The issue is apparently a naming conflict between the custom permit matcher defined here and the built-in Pundit rspec method permit, as discussed in this post... https://github.com/elabs/pundit/issues/130. Once the custom pundit_matcher method is renamed to something else (like authorize) it works great for me. Just in case it's helpful...

Yes, you can't have both matchers included at the same time. Please see #130

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DannyBen picture DannyBen  路  6Comments

epinault picture epinault  路  6Comments

lnikkila picture lnikkila  路  5Comments

cthielen picture cthielen  路  5Comments

jarosluv picture jarosluv  路  6Comments