The answer to my question consists of multiple parts. I hope this clarifies the setup to everyone else who deals with a similar configuration.
1. Ability Precedence
First of all please mind that the order of ability rules does matter as described in Ability Precedence. After realizing this fact I came up with an updated set of ability rules.
# /models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
# Create guest user aka. anonymous (not logged-in) when user is nil.
user ||= User.new
if user.has_role? :admin
can :manage, :all
else
# logged in user
if user.has_role? :user
can :manage, Farm, :user_id => user.id
can :create, Farm
end
# guest user aka. anonymous
can :read, :all
end
end
end
2. FarmsContoller
Keep it simple in the index action. load_and_authorize_resource
is your friend.
# /controllers/api/v1/farms_controller.rb
class Api::V1::FarmsController < ActionController::Base
load_and_authorize_resource
rescue_from CanCan::AccessDenied do |exception|
redirect_to farms_path, alert: exception.message
end
respond_to :json
def index
respond_with(@farms)
end
end
3. Get request with authentication token
Do not forget to pass the token when you request data from the farms controller.
# # /spec/api/v1/farm_spec.rb
get "#{url}.json", auth_token: :token
The token must be added in the User model as follows.
# app/models/user.rb
class User < ActiveRecord::Base
before_save :ensure_authentication_token
And the name of the method can be configured in the initializer of Devise.
# config/initializers/devise.rb
config.token_authentication_key = :auth_token