Eric Mathison
Eric Mathison

Reputation: 1256

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

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.

Upvotes: 1

Views: 402

Answers (2)

coorasse
coorasse

Reputation: 5528

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

Upvotes: 0

mechnicov
mechnicov

Reputation: 15318

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

Upvotes: 2

Related Questions