I got Article model with enum field enum status: [:pending, :done]
.
Here's my ability file
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.member?
can :read, Article.done
end
end
end
In view I am trying to render Article.done collection for member but nothings renders.
<% if can? :read, Article.done %>
<%= render partial: 'article', collection: Article.done, as: :article %>
<% end %>
Therefore I have a question: is there any possible way to work with enum in CanCanCan?
I may be wrong, but I think that enum
only creates instance
methods:.
@article = Article.find params[:id]
@article.done?
I was wrong...
Scopes based on the allowed values of the enum field will be provided
as well. With the above example:
Conversation.active
Conversation.archived
--
I'll delete this if it doesn't work; I would be evaluating against the hash of conditions, not the class itself:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.member?
can :read, Article, status: Article.statuses[:done]
end
end
end
Update
Several important things to consider.
Firstly, when using hash
conditions:
Important: If a block or hash of conditions exist they will be ignored when checking on a class, and it will return true.
This means that you cannot call specific conditions on an "ability" whilst passing a class, it has to be called on an instance of an object.
Secondly, it seems CanCanCan has some issues evaluating enum
values, which makes the following code necessary:
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.member?
can :read, Article do |article|
article.done?
end
end
end
end
You then need to pass the article
instance to the can?
method:
#app/views/articles/index.html.erb
<table>
<%= render @articles %>
</table>
#app/views/articles/_article.html.erb
<% if can? :read, article %>
<tr>
<td>Title:</td>
<td><%= article.title %></td>
<td><%= article.status %></td>
</tr>
<% end %>