Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom error messages in policies #655

Closed
wants to merge 1 commit into from

Commits on May 14, 2020

  1. Support custom error messages in policies

    This commit allows policies to define the error messages
    set on `Pundit::NotAuthorizedError` exceptions when `#authorize` fails.
    The rationale is described in detail in GitHub issue varvet#654[0],
    and summarized below.
    
    Some queries can fail in multiple ways; for instance,
    
        class PostPolicy
          def update?
            if record.author != user
              ... # failure case 1
            elsif record.archived
              ... # failure case 2
            end
    
            true
          end
        end
    
    In their controllers, users might wish
    to handle different failure modes in different ways,
    but prior to this commit, there was only one way to tell the difference—
    namely, by raising errors inside the query method:
    
        def update?
          if record.author != user
            raise Pundit::NotAuthorizedError, 'You’re not the author!'
          elsif record.archived
            raise Pundit::NotAuthorizedError, 'This post is old news!'
          end
    
          true
        end
    
    This breaks the expectation that query methods should return booleans,
    which in turn breaks a pattern for using query methods in views:
    
        <% if policy(@post).update? %>
          <%= link_to "Edit post", edit_post_path(@post) %>
        <% end %>
    
    973b63b added a `reason` option to the NotAuthorizedError initializer,
    but ultimatly required the same approach of raising errors in queries.
    
    ---
    
    This commit enables a cleaner method of passing a custom error message
    to exceptions from within policies,
    without violating the expectations of where exceptions are raised from.
    
        class PostPolicy
          attr_accessor :error_message
    
          def update?
            self.error_message = if record.author != user
                                   'You’re not the author!'
                                 elsif record.archived
                                   'This post is old news!'
                                 end
    
            error_message.nil?
          end
        end
    
    [0]: varvet#654
    rlue committed May 14, 2020
    Configuration menu
    Copy the full SHA
    a129293 View commit details
    Browse the repository at this point in the history