使用 Pundit 授权时获取布尔值而不是记录

Getting boolean instead of record when authorizing with Pundit

根据 the Pundit readme authorize 应该 return 记录,但是当我调用它时我得到 true.

authorize returns the object passed to it, so you can chain it like this:

Controller:

def show
  @user = authorize User.find(params[:id])
end

宝石文件:

gem 'rails', '~> 5.1.1'
gem 'devise', '~> 4.3'
gem 'pundit', '~> 1.1'

我的控制器:

class PostsController < ApplicationController
  skip_before_action :authenticate_user!, only: [:show, :index]
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  def show
    # just for debugging purposes
    raise "Post is a #{@post.class.name}!" unless @post.is_a? Post
  end

  def set_post
    # this should return an instance of post
    @post = authorize Post.find(params[:id])
  end
end

政策:

class PostPolicy < ApplicationPolicy

  class Scope < Scope
    def resolve
      scope.all
    end
  end

  def show?
    true
  end

  # ...
end

规格:

require 'rails_helper'
RSpec.describe "Posts", type: :request do
  subject { response }

  describe "GET /posts/:id" do
    let!(:post) { create(:post) }
    before { get post_path(post) }
    it { should be_successful }
  end
end

失败消息:

  4) Posts GET /posts/:id 
     Failure/Error: raise "Post is a #{@post.class.name}!" unless @post.is_a? Post

     RuntimeError:
       Post is a TrueClass!

虽然通过以下方式解决这个问题非常简单:

def set_post
  @post = Post.find(params[:id]).tap do |p|
    @post = Post.find(params[:id]).tap { |r| authorize r }
  end
end

我很好奇为什么它没有按照自述文件所述工作。这是一个错误还是我只是遗漏了什么?

返回记录显然是 master 中的一个更改,未反映在 1.1 版本中。

# Retrieves the policy for the given record, initializing it with the
# record and user and finally throwing an error if the user is not
# authorized to perform the given action.
#
# @param user [Object] the user that initiated the action
# @param record [Object] the object we're checking permissions of
# @param record [Symbol] the query method to check on the policy (e.g. `:show?`)
# @raise [NotAuthorizedError] if the given query method returned false
# @return [true] Always returns true
def authorize(user, record, query)
  policy = policy!(user, record)

  unless policy.public_send(query)
    raise NotAuthorizedError, query: query, record: record, policy: policy
  end

  true
end

解决方法是:

def authorize(record, query = nil)
  super
  record 
end