In controller specs instead of relying on Pundit to instantiate the correct
policy object allow it to be injected into the controller. More often than not
a double is used in controller specs which means the policy cannot be
inferred. This also allows us to double the policy to ensure that on a unit
level the rights methods are being called on callaborators.
class PostsController < ApplicationController
attr_writer :post
helper_method :post
def create
authorize post
post.save
respond_with post
end
private
def post
@post ||= Post.new post_attributes
end
end
describe PagesController do
let(:policy) { double 'SomePolicy', create?: true }
before do
controller.policy = policy
end
it 'delegates authorization to policy' do
expect(policy).to have_received(:create?)
end
end
Add spec for injecting policy.
Use `or` instead of ternary operator.
Allow policy_scope to be injected for controller tests.
See the readme changes for an example. In short, this behaves
like verify_authorized but is useful for actions that find a
collection (like index) and don't authorize instances.
The `BlogPolicy -> "BlogPolicy" -> "Blog" -> "BlogPolicy" -> BlogPolicy`
issue @jnicklas pointed out has been resolved. For example, given
```ruby
class BlogPolicy < Struct.new(:user, :blog); end
class Blog; end
class ArtificialBlog < Blog
def self.policy_class
BlogPolicy
end
end
```
The above string manipulation/casting is prevented; the `BlogPolicy`
class will be immediately returned to `policy` and on to be evaluated.
Anonymous classes are now supported too. For example, given
```ruby
class BlogPolicy < Struct.new(:user, :blog); end
class Blog; end
class ArtificialBlog < Blog
def self.policy_class
Struct.new(:user, :blog) do
def create?
true
end
end
end
end
```
The `Struct` will be returned and evaluated as any other policy.