0

So I have a Post model. My posts can be either published or unpublished. I am using Rolify, CanCanCan and Devise.

What I want to happen is my :admin users, should be able to view the Post#Show action of all Posts, but my :member or guest users (i.e. non-logged in) should only ever be able to see Post.published posts.

My ability.rb looks like this:

   if user.has_role? :admin
        can :manage, :all
    #Member
    elsif user.has_role? :member
        can :read, :all
        can :create, Post
        can :status, Post
        can :update, Post do |post|
            post.try(:user) == user
        end
    #Guest
    else
        can :read, :all
        can :create, Post
        can :status, Post
    end

I tried doing this, for both :member and Guest, but it gave me an endless redirect loop on my Post#Index page - which is my root_path:

    can :read, Post.published

Where Post.published returns an array of all the posts with publication_status = "published".

This is how I declared that on my Post.rb:

enum publication_status: [ :unpublished, :published ]

How do I achieve this?

marcamillion
  • 32,933
  • 55
  • 189
  • 380

2 Answers2

0

I figured this out.

In my Post#Show, I simply did this:

  def show
    if current_user and current_user.has_role? :admin or :editor
      @post = Post.find(params[:id])
    else
      @post = Post.published.find(params[:id])
    end
  end

That works like a charm.

If someone has a more elegant way, say inside the ability.rb I would love to know.

I tried many permutations using blocks and all this jazz in the ability.rb but nothing worked.

I also had to remove the default added set_post method in my controller, because cancancan already loads_and_authorize the resource.

marcamillion
  • 32,933
  • 55
  • 189
  • 380
0

Try the following

#Member
elsif user.has_role? :member
    can :read,   Post, publication_status: :published
    can :create, Post
    can :status, Post
    can :update, Post, user_id: user.id
 # same goes for the Guest user

this will work given that you have a column named publication_status in the Post model

a14m
  • 7,808
  • 8
  • 50
  • 67