So, I'm trying to use the gem pundit. I'm just trying to figure out how to have an index view for users and admins. I want to render all results for an admin and only related posts for a user. I've googled and searched on github, but I'm not find any luck. What do I have to put in my policy and controller?
original code
class PostsPolicy
attr_reader :current_user, :model
def initialize(current_user, model)
@current_user = current_user
@post = model
end
def index?
@current_user.admin?
end
end
controller
class PostsController < ApplicationController
before_filter :load_user
before_filter :authenticate_user!
after_action :verify_authorized
def index
@posts = Post.order('title').page(params[:page]).per(25)
authorize User
end
private
def load_user
@user = User.find_by_id(params[:user_id])
end
end
second update
class PostsPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(user: user)
end
end
end
end
controller
class PostsController < ApplicationController
before_filter :load_user
before_filter :authenticate_user!
after_action :verify_authorized
def index
@posts = policy_scope(Post).order('title').page(params[:page]).per(25)
authorize User
end
private
def load_user
@user = User.find_by_id(params[:user_id])
end
end
third update
class PostPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(user: user)
end
end
end
def index?
user.admin? || user.posts.count > 0
end
end
controller
class PostsController < ApplicationController
before_filter :load_user
before_filter :authenticate_user!
after_action :verify_authorized
def index
@posts = policy_scope(Post).order('title').page(params[:page]).per(25)
authorize User
end
private
def load_user
@user = User.find_by_id(params[:user_id])
end
end
** final update with working code **
class PostPolicy
attr_reader :user, :model
def initialize(user, model)
@user = user
@post = model
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(user: user)
end
end
end
def index?
user.admin? || user.posts.count
end
end
controller
class PostsController < ApplicationController
before_filter :load_user
before_filter :authenticate_user!
after_action :verify_authorized
def index
@posts = policy_scope(Post).order('title').page(params[:page]).per(25)
authorize Post
end
private
def load_user
@user = User.find_by_id(params[:user_id])
end
end
What you're looking for is a Scope:
class PostsPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(user: user)
end
end
end
end
Then in your controller
def index
@posts = policy_scope(Post).order('title').page(params[:page]).per(25)
authorize User
end
Edit
As a side note, authorize User
will probably not serve you well in the long run. You're essentially creating an index policy that would need to serve every index. If you want to to authorize visibility to the index page you can still do something like this in your policy:
def index?
user.admin? || user.posts.count > 0
end
Assuming that relationship is set up, then you would call authorize Post
in your index controller before your policy_scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With