How do I specify a custom exception message from my ability.rb?
Asked Answered
F

3

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
Flammable answered 12/12, 2016 at 7:42 Comment(6)
What is with the ELSIF condition. Is the IF condition existing somewhere before the ELSIF condition? I a m thinking that's the problem.Cistaceous
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: github.com/CanCanCommunity/cancancan/wiki/Exception-Handling. Having ability.rb produce the right exception is only half the job.Rhetic
@Rhetic What specifically within my controller are you looking for? My controller is beastly, so just trying to narrow it down for you.Flammable
@Rhetic 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.Flammable
@Flammable so it sounds like you're wanting to specify custom messages for a flash alert from a model – is that correct?Corrosive
@Flammable any luck with any of the answers below? if so, mark the accepted answer or post what you did that finally solved it.Rhetic
P
2

This is what you are looking for:

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

Pantisocracy answered 12/12, 2016 at 8:3 Comment(1)
Thats what led me to try the above. But it doesnt work.Flammable
C
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
Condolence answered 21/12, 2016 at 2:36 Comment(0)
R
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.

Rhetic answered 19/12, 2016 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.