Description
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!