Skip to content

Class vs Instance subjects #57

@jrochkind

Description

@jrochkind

As I'm trying to do something a bit more convoluted in my app, I'm realizing access-granted doesn't work quite as I thought for being able to kind of interchangeably use a Class (with the semantics "all of them", as in the can? :create, Post example) and an instance of a class interchangeably.

I was imagining on the same permission you could kind of use both interchangeably. But if we try say:

    role :admin, { role: "admin" } do
      can :manage, Post
    end

    role :user do
      can :manage, Post, { published: true }
    end

and then we try can? :create, Post, then of course you get undefined method published' for Post:Class`.

Because it's trying to call published on the specific Post object you passed in, of course it is, you did specify that condition naturally. And Post.published is not a thing.

So I guess any given permission, you need to decide you are going to only use with a class object (like in README example for :create), or only use it with an instance (like in README examples with :update or :make_manager).

In my example above, I shouldn't say can :manage, Post, but instead maybe:

can [:read, :update, :destroy], Post, { published: false }

and then maybe only can :create, Post only on admin role.

My actual use case, I was hoping to mix and match. I had a read role defined like above, where admin's can read everything, everyone else can only read published things.

So when I have a specific item, of course I can just ask can? :read, specific_post,

But I want to know if I should show a UI widget, say, "include unpublished posts", and I should only show that widget to those who can see even unpublished posts, and I was hoping to be able to do can? :read, Post and have it be only true for Post.

But that won't work.

Curious if you have any advice. Should I just define a new permission :can_see_unpublished_posts which I give only to admin, so I can check that to decide whether to show the "include unpublished posts" button? It seems duplicative, but...

I suppose we could do another PR where access_granted, for hash conditions, first checks to make sure the method exists (with respond_to?), and if it doesn't, that's just false?

Or I guess I could write the condition long-hand:

    can :read, Post do |post, user|
       post.respond_to?(:published) && post.published
    end

And now I guess it'll work if I ask can? :read, Post (answer is no if they can only read published posts, because Post.respond_to?(:published) is false.... but still return properly for Post instances (based on published).

I'm not super happy with any of these solutions, I am curious your feedback!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions