6

In my ability.rb, I have the following rule:

elsif user.has_role? :demo
  can :read, Profile, demo_featured: true, demo_linked: true, message: "To access this profile, please subscribe here."

But that doesn't produce the message I want.

How do I get this specific rule to produce the message I want?

Edit 1

Here is the full ability.rb if condition:

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    alias_action :create, :show, :new, :destroy, to: :csnd

    if user.has_role? :admin
      can :manage, :all
    elsif user.has_role? :coach
      # do some stuff
    elsif user.has_role? :demo
      can :read, Profile, demo_featured: true, demo_linked: true
    elsif user.has_role? :player
      # can do some stuff
    else
      can :read, Profile
    end    
  end

These are some bits from my ProfilesController:

  before_action :set_profile, only: [:show, :edit, :update, :destroy, :invite_user, :profiles]

    def set_profile
      @profile = Profile.published.includes(:grades, :positions, :achievements, :videos, :transcripts).friendly.find(params[:id])
    end
marcamillion
  • 32,933
  • 55
  • 189
  • 380
  • What is with the ELSIF condition. Is the IF condition existing somewhere before the ELSIF condition? I a m thinking that's the problem. – Afolabi Olaoluwa Dec 15 '16 at 07:59
  • 1
    Post your controller code. You have to catch the exception in your controller and use its message in the flash or alert part of the response, as stated here: https://github.com/CanCanCommunity/cancancan/wiki/Exception-Handling. Having ability.rb produce the right exception is only half the job. – mlabarca Dec 16 '16 at 19:57
  • @mlabarca What specifically within my controller are you looking for? My controller is beastly, so just trying to narrow it down for you. – marcamillion Dec 17 '16 at 18:27
  • @mlabarca Actually, there is nothing specific about this logic in my `ProfilesController#Show`. What should I put there? The issue is that the logic works, I just want the message customized. I also updated the question with more code. – marcamillion Dec 17 '16 at 18:34
  • @marcamillion so it sounds like you're wanting to specify custom messages for a flash alert from a model – is that correct? – jeffdill2 Dec 18 '16 at 18:23
  • @marcamillion any luck with any of the answers below? if so, mark the accepted answer or post what you did that finally solved it. – mlabarca Dec 22 '16 at 12:19

3 Answers3

2

This is what you are looking for:

https://github.com/CanCanCommunity/cancancan/wiki/Exception-Handling

Astranormal
  • 106
  • 5
2

The cancan docs give examples of customizing the message when you authorize! in the controller, and when you manually raise an error, but there doesn't seem to be any mechanism for specifying messages in ability.rb.

Instead, you could catch and modify it in your ApplicationController:

class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied do |exception|
    if current_user.has_role? :demo
      redirect_to :back, :alert => "To access this profile, please subscribe here."
    end
    # render 403, etc.
  end
end
anyarms
  • 349
  • 1
  • 8
1

Look for rescue_from CanCan::AccessDenied in your main application controller or in your specific controller. It should do something like redirecting to a login page. In my case it's something like this:

rescue_from CanCan::AccessDenied do ||
  redirect_to new_user_session_path
end

Since you're producing a different exception message and then displaying it it'd probably be like this, using the flash:

rescue_from CanCan::AccessDenied do |exception|
  flash[:notice] = exception.message
  redirect_to new_user_session_path
end

Your own logic may vary depending on how you want to handle when the user doesn't have access. It's possible you may even have it setup in a per-controller basis, but this should be the gist of it.

mlabarca
  • 796
  • 7
  • 16