I am trying to learn how to use Pundit with my Rails 4 app.
I have the following models:
class User < ActiveRecord::Base
has_one :profile
has_
In your first example, there's a couple of issues. Firstly, @eoi
does not exist, and can't exist. The @eoi
variable is set in the controller, and this is a different object. It doesn't work in the same way as your views where this is accessible, so this will never be set.
Equally, the eoi
variable will not be set, as your initialize
method is only assigning the user
and resource
variables, so they're the only two you have access to (unless you rename)
The scope in the policy works a little differently to how you think it works. The policy itself generally takes the user logged in, and a class, or a record that you are authorising. The scope however, doesn't normally take a record as the second argument. It is a scope, so either an active record sub-class, or a relation. You're not restricted to this however, and you could work around it by supplying a record but do note this is not normal behaviour for Pundit.
In order to achieve what you're after, you should only have to make a few adjustments:
class EoiPolicy < ApplicationPolicy
class Scope
attr_reader :user, :eoi
def initialize(user, eoi)
@user = user
@eoi = eoi
end
def resolve
if user.profile.project.id == eoi.project_id
Eoi.where(project_id: user.profile.project.id)
elsif user.id == eoi.user_id
Eoi.where(user_id: user.id)
else
nil
end
end
end
def index?
user.profile.project.id == record.project_id or user.id == record.user_id
end
def new?
true
end
def show?
user.profile.project.id == record.project_id? or user.id == record.user_id
end
def edit?
user.id == record.user.id
end
def create?
true
end
def update?
user.id == record.user.id
end
def destroy?
user.id == record.user.id
end
end
The main changes here are that the attr_reader :user, :scope
is now attr_reader :user, :eoi
which will give you access to eoi
within that scope.
Access to this is no longer prefixed with @
as this is in-line with how pundit works.
Throughout the rest of the policy, @eoi
again cannot work, but this has been changed to record
(assuming this is what it is in ApplicationPolicy). Please bear in mind the the Scope, and the rest of the policy are two different classes.
With this setup, you should now be able to simply call policy_scope(@eoi)
from within your controller. Note the usage of the @eoi
variable here and NOT the Eoi
class as before. This is crucial, as without this, you won't have access to things like user_id
or project_id
as those methods don't exist in the Eoi class, but only a record.
I've also removed the ?
symbols from the end of your if conditions. These are generally used to signify that the method being called returns a boolean, whereas you had them on the end of something that simply returns an integer. I'd imagine you'd actually get an error saying the method doesn't exist but if you've renamed things then you may want to put them back, but as I say that does go against ruby coding styles.
And on a side-note, using or
or and
in statements instead of ||
or &&
can on the odd occasion behave differently to how you expect. In most scenarios it's fine, but it doesn't technically mean the same thing.
Hope this all helps, let me know if you have any further issues with it.