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

时间:2017-05-18 10:26:45

标签: ruby-on-rails pundit

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

  

authorize返回传递给它的对象,因此你可以将它链接起来   这样:

     

控制器:

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

的Gemfile:

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

我非常好奇为什么它不能像自述文件那样工作。这是一个错误还是我错过了什么?

1 个答案:

答案 0 :(得分:0)

返回记录显然是主人的变化,未在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