How can I use CanCanCan's `can?` method inside a view component?

176 Views Asked by At

As best I can tell, CanCanCan's can? method is available to normal views in Rails but not view components by default. What is the appropriate way to include the can? method in my view components? I already have my app/models/ability.rb file set up. In my other views I'm using can?(:create, Post.new(project: @project)) but would love to use this in my Header::HeaderComponent view component as well.

I know I can add include CanCan::Ability within my component class but that doesn't seem right as it doesn't appear to make use of the rules I have defined in my ability class or have access to the current user.

2

There are 2 best solutions below

0
On BEST ANSWER

What's about implement same way like in the gem

def can?(*args)
  current_ability.can?(*args)
end

def cannot?(*args)
  current_ability.cannot?(*args)
end

def current_ability
  @current_ability ||= ::Ability.new(current_user)
end

Of course you need somehow pass current user to your component. Official guidelines suggest such way

class Header::HeaderComponent < ViewComponent::Base
  attr_reader :current_user

  def initialize(current_user:)
    @current_user = current_user
  end
end
0
On

In ViewComponents you can always delegate methods to helpers. Your can? and cannot? methods are helpers. Therefore you can simply:

class Header::HeaderComponent < ViewComponent::Base
  delegate :can?, :cannot?, to: :helpers
end

of course you should do the same with any other helper method that you need. I usually like to follow the pattern of having an ApplicationComponent that any other component inherits from.

class ApplicationComponent < ViewComponent::Base
  delegate :can?, :cannot?, to: :helpers
end

class Header::HeaderComponent < ApplicationComponent

end