I've been going through the railscast on using the cancan gem but am stuck on how to only allow a user to visit their own show page.
My code looks like this:
Ability model
class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.role == "admin"
      can :manage, :all
    else
      can :read, :all
      if user.role == "author"
        can :create, Review
        can :update, Review do |review|
          review.try(:user) == user
        end
        can :update, User do |user|
          user.try(:current_user) == current_user
        end
      end
      if user.role == "owner"
        can :update, Venue
      end
    end
  end
end
User controller
class UsersController < ApplicationController
  load_and_authorize_resource
end
A user (author) can only update their own reviews, but can currently view all users show pages by altering the URL.
What am I missing here?
Constraints can be passed right in your ability class, even easier than the way you're trying. I'm sure this is missing some abilities you're looking to have, but this should get you started. I'm assuming Reviews :belong_to Users with a foreign key of :user_id. It also looks like you need some similar kind of constraint for Venues, but you didn't have it in your code so I didn't put it in this.
class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.role == "admin"
      can :manage, :all
    elsif user.role == "author"
      can :create, Review
      can :update, Review, :user_id => user.id
      can [:show, :update], User, :id => user.id
    elsif user.role == "owner"
      can :update, Venue
      can [:show, :update], User, :id => user.id
    else
      can [:show, :update], User, :id => user.id
    end
  end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With