【问题标题】:Pundit::NotDefinedError: unable to find policy `UserPolicy`Pundit::NotDefinedError:无法找到策略“UserPolicy”
【发布时间】:2016-05-27 13:42:23
【问题描述】:

我一定是做错了什么,或者我需要戴眼镜。我在这里学习本教程:

http://vaidehijoshi.github.io/blog/2015/09/29/using-pundit-the-cool-kid-of-authorization/

我已按照说明在app/policies 文件夹中创建了application_policy.rb 文件和user_policy.rb 文件。

Pundit 似乎没有在 IntegrationTests 中检测到我的 UserPolicy 文件。

我的设置

  • Ruby on Rails 5 RC1
  • Ruby 2.2.4p230
  • Knock gem 进行 JWT 身份验证
  • 权威 1.1.0

user_policy.rb

class UserPolicy < ApplicationPolicy    
  def update?
    user == resource
  end
end

在我的 UserController 中,我定义了 REST API 操作。目前,我只是在测试“更新”操作:

用户控制器

def update
  user = User.find_by({id: params[:id]})

  authorize user

  render json: { error: "Failed to find" }, status: :not_found and return unless user

  if user.update!(user_params)
    render json: user
  else
    render json: { error: "Not found" }, status: :not_found
  end
end

users_controller_test.rb

test "update other user's data should raise NotAuthorized exception" do
  @user_two = users(:two)

  put user_path(@user_two.id), params: { first_name: "Jim" }, headers: @authorization_header
  assert_response :success # forcing fail test for now to test plumbing
end

我收到以下错误:

.E

Error:
UsersControllerTest#test_update_other_user's_data_should_raise_NotAuthorized_exception:
Pundit::NotDefinedError: unable to find policy `UserPolicy` for `#<User id: 298486374, first_name: "MyString", last_name: "MyString", email: "MyString", password_digest: "MyString", created_at: "2016-05-27 13:30:07", updated_at: "2016-05-27 13:30:07", role_id: nil>`
    app/controllers/users_controller.rb:42:in `update'
    test/controllers/users_controller_test.rb:60:in `block in <class:UsersControllerTest>'

任何想法我可能做错了什么?

编辑

如果有帮助,我的 UserControllerTest 文件如下所示:

require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest
  def authenticate
    token = Knock::AuthToken.new(payload: { sub: users(:one).id }).token
    @authorization_header = { HTTP_AUTHORIZATION: "Bearer #{token}" }
  end

  setup do
    # load "#{Rails.root}/db/seeds.rb"
    Rails.application.load_seed
    authenticate
    @user = users(:one)
  end

  test "logged in user should return ok" do
    get users_path, headers: @authorization_header
    assert_response :ok
  end

  test "not logged in user should return unauthorized" do
    get users_path
    assert_response :unauthorized
  end

  test "user json should not contain password_digest" do
    get user_path(@user.id), headers: @authorization_header
    assert_response :ok
    json = JSON.parse(response.body)
    assert json.key?("password_digest") == false
  end

  test "create user without authorization header should return created" do
    user = {
      first_name: "Bob",
      last_name: "Brown",
      email: "bob@gmail.com",
      password: "abc",
      password_confirmation: "abc"
    }

    post users_path, params: user
    assert_response :created
    json = JSON.parse(response.body)
    assert !json.empty?
  end

  test "update user should return ok" do
    put user_path(@user.id), params: { first_name: "Bob"}, headers: @authorization_header
    assert_response :ok

    updated_user = User.find_by({id: @user.id})

    assert_equal "Bob", updated_user.first_name
  end

  test "update other user's data should raise NotAuthorized exception" do
    @user_two = users(:two)

    put user_path(@user_two.id), params: { first_name: "Jim" }, headers: @authorization_header
    assert_response :success
  end

  test "delete user shoudl return ok" do
    assert_difference "User.count", -1 do
      delete user_path(@user.id), headers: @authorization_header
    end
  end
end

在一小时前添加 Pundit 内容之前,我的所有测试都已通过。

【问题讨论】:

  • 文件实际上是叫UserPolicy.rb吗?在 ruby​​ 中,使用下划线命名文件是小写的,例如:user_policy.rb。如果是这种情况,那就是你的问题。
  • 抱歉,输入错误。不,文件名为user_policy.rb
  • 所以澄清一下,是不是只有测试不起作用?如果您运行服务器并手动执行某个操作,它会起作用吗?
  • 也可能是 Rails 服务器需要重新启动才能启动并开始自动加载 /app 中的新文件夹。如果您使用的是 spring 之类的 forker,则可能需要重新启动它。
  • 只是补充一点,您是否使用spring 运行测试?例如,当您更新 gem 依赖项时,这应该自动重启 - 但是强制手动重启值得一试。

标签: ruby-on-rails ruby ruby-on-rails-5 pundit


【解决方案1】:

为了修复,我跑了:

bin/spring stop
bin/spring binstub --remove --all
bundle update spring
bundle exec spring binstub --all

【讨论】:

    【解决方案2】:

    好的....我不知道到底发生了什么,但显然,我退出了我输入代码的所有 Mac 终端和 Atom IDE。

    然后我打开终端并再次执行rails test 命令,这次成功了:

    ....E
    
    Error:
    UsersControllerTest#test_update_other_user's_data_should_raise_NotAuthorized_exception:
    Pundit::NotAuthorizedError: not allowed to update? this #<User id: 298486374, first_name: "MyString", last_name: "MyString", email: "MyString", password_digest: "MyString", created_at: "2016-05-27 15:19:51", updated_at: "2016-05-27 15:19:51", role_id: nil>
        app/controllers/users_controller.rb:42:in `update'
        test/controllers/users_controller_test.rb:60:in `block in <class:UsersControllerTest>'
    

    奇怪的...

    TL;DR

    1. 退出 IDE 和终端
    2. 重新打开终端,然后重试

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多