Reputation: 5178
I have a Blog
model which has different states. In order to keep a skinny controller and follow the convention of only having CRUD operations per controller, I followed DHH's namespacing controllers pattern and namespaced out the Blog
controller.
Now I have a Blogs::NewDraft
controller, a Blogs::AwaitingApproval
controller, and a Blogs::Active
controller.
The issue is with writing my policies to authorize the actions within these namespaced controllers. All the actions in all the namespaced controllers are all authorizing the same Blog
model object. The issue is that I need each of the namespaced controllers to authorize in a matching namespaced policy (as opposed to all of the namespaced controllers authorizing within the same blog_policy.rb
file.)
Basic Example: For a restful resource with a restful controller that is NOT namespaced you do it something like this:
#app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
def index
authorize :blog
@blogs = Blog.all
end
def show
@blog = Blog.find(1)
authorize @blog
end
end
And now the matching Policy
#app/policies/blogs_policy.rb
class BlogPolicy < ApplicationPolicy
def index?
user.admin?
end
def show?
record.author == current_user
end
end
You do it like that when you don't namespace.
Current Code to Try to get Namespacing to work with Pundit: I am namespacing. I am still authorizing a Blog
object, but I need to authorize the actions within each namespaced controller within a namespaced policy:
#app/controllers/blogs/new_drafts.rb
class Blogs::NewDraftsController < ApplicationController
def index
# doesn't work
authorize Blog::NewDrafts
@blogs = Blog.new_drafts
end
def show
@blog = Blog.find(1)
#doesn't work either
authorize @blog, Blog::NewDraft
end
end
So I want that namespaced controller to NOT route to app/policies/blog_policy.rb
, but instead to app/policies/blogs/new_draft_policy.rb
#app/policies/blogs/new_draft_policy.rb
class Blogs::NewDraftPolicy < ApplicationPolicy
def index?
user.admin?
end
def show?
# the record is a blog from the Blog Model
record.author == current_user
end
end
Pundit Documentation and Usage
Upvotes: 1
Views: 1018
Reputation: 5178
Don't know how to route to namespaced policy AND pass in the Blog
record. However: below is how you do it when your namespaced policy is able to authorize only based on the current user's permissions/roles:
#app/controllers/blogs/new_drafts.rb
class Blogs::NewDraftsController < ApplicationController
def index
authorize [:blogs, :new_draft]
@blogs = Blog.new_drafts
end
end
#app/policies/blogs/new_draft_policy.rb
class Blogs::NewDraftPolicy < ApplicationPolicy
def index?
user.admin?
end
end
Upvotes: 1