Having Rails 4.2.0 app with strong_parameters and shoulda-matchers 2.7.0 and this spec:
describe AlbumPolicy do
subject { described_class }
let(:user) { User.new }
permissions :edit? do
it "grants access if album belongs to a user" do
expect(subject).to permit(user, Album.new(user: user))
end
end
end
The test will fail with:
1) AlbumPolicy edit? grants access if album belongs to a user
Failure/Error: expect(subject).to permit(user, Album.new(user: user))
Shoulda::Matchers::ActionController::StrongParametersMatcher::ActionNotDefinedError:
You must specify the controller action using the #for method.
# .../shoulda-matchers-2.7.0/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb:242:in `ensure_action_and_verb_present!'
# .../shoulda-matchers-2.7.0/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb:190:in `matches?'
Hi @Holek, I was having this problem too. I resolved it specifying the type meta on my policy specs.
describe AlbumPolicy, type: :policy do
# ...
end
With this, shoulda-matchers didn't conflict with its controller #permit matcher.
Which version of RSpec you are using?
I think Pundit behaves in the correct way and only includes the permit matcher in its own RSpec context. This is really a problem with shoulda including their matchers where they don't belong. They should limit them to only controller specs. Please file this issue with shoulda instead.
I ran into this as well. Is there are a workaround for this?
Hi @KurtRMueller, as you can see in the implementation of Pundit's custom matchers, they're going to behave normally if policies are within the /spec/policies folder and with type: :policy meta.
Shoulda-matchers permit matcher only scopes it to controller specs in its earlier versions.
Thanks for the quick response @tiagoamaro. In this case, my policy spec file is indeed in the /spec/policies folder and does have the type: policy meta added on to it.
**Edit: I fixed this by including shoulda-matchers first and then pundit/rspec.
:+1: @KurtRMueller ,
Great that you fixed it and detailed how. Hopefully, shoulda-matchers 3.0 will soon launch and stop this confusion.
Here's a question and it's up for debate:
Does any one gem have a right to claim the permit verb? Permit is ambiguous enough to where I could can see why both pundit and shoulda-matchers use the verb. In pundit's case, it's obviously policy permissions - in shoulda-matcher's case, it's for whitelisted parameters.
This could be a simple fix for both parties. Simply create an alias for the permit method: permit_parameters for shoulda-matchers and authorize or something similar for pundit.
Anyway, it's just a thought. Thanks for all your help people and I really do love Pundit :).
The difference is that Pundit is only "claiming" the permit name within the spec group that Pundit itself has created. Pundit's permit matcher is only available inside type: :policy specs. You could make a case that other gems might want to create something called a policy, but there currently isn't one, so that's a theoretical argument, and I think "dibs" applies in that case ;) shoulda however is including its matcher, which clearly only works with controller specs into _all_ specs.
Specifying type: :policy didn't help.
I removed require 'pundit/rspec' from spec_helper, and added to policy spec right after require 'spec_helper'. Now the error is gone.
+1 on @KurtRMueller's thought.
@denispeplin thanks. yours was the solution for me too
@KurtRMueller thank you, it works well now.
Most helpful comment
Specifying
type: :policydidn't help.I removed
require 'pundit/rspec'fromspec_helper, and added to policy spec right afterrequire 'spec_helper'. Now the error is gone.