I have reviews set up similar to Airbnb.
These abilities should allow a guest to review a host, and a host to review a guest:
# ability.rb
can [:show], [Review] do |review|
if review.reviewable_type == "Host"
review.booking.guest_id == user.guest.id
elsif review.reviewable_type == "Guest"
review.booking.host_id == user.host.id
end
end
Here's the controller:
class ReviewsController < ApplicationController
authorize_resource
before_action :set_review, only: [:show]
def show
end
private
def set_review
@review = Review.find_by_id(params[:id])
end
end
When testing, everything works
host = Host.first
review = Review.first # A review of a host
ability = Ability.new(host.user)
ability.can?(:show, review)
# Returns false as expected
review2 = Review.second # A review of a guest
ability.can?(:show, review2)
# Returns true as expected
So everything's fine until this point.
But when I login as the host and visit the review for myself, I can review myself! The exact logic above denies access when it's tested in the console.
Why does cancancan prevent access in the console, but allow access in the browser?
Total noob mistake.
I had
But authorize_resource should be called after the before_action that sets the model instance for the action.
So after this simple reordering, it works as expected: