Eager load associations to check hash conditions.
Why is this needed?
When checking a user has the ability to perform an action on an instance using a deeply nested hash, it's possible to encounter expensive N+1 queries, which slow your application down.
# ability.rb
def initialize(user)
return unless user.present?
# User can see Posts before they're published, of the authors they're mentoring
can :show, Post, status: :preview, authors: { mentors: { id: user.id } }
end
# Controllers
def show
@post = Post.find(params[:id])
# Causes an N+1 problem - a separate SQL query is made to find the mentors of each author
authorize! :show, @post
end
It's possible to audit your code and manually eager load the associtions needed for each permission check, but that's slow, error prone and likely to get out of sync if you redefine your abilities.
Or you could use cancan-eager_load
to automatically do it for you.
Installation
Add this line to your application's Gemfile:
gem 'cancan-eager_load'
And then execute:
$ bundle
Or install it yourself as:
$ gem install cancan-eager_load
Usage
Just use CanCanCan's helper methods as normal: authorize!
, can?
and cannot?