Rails 5 - Pundit - 索引解析范围方法

时间:2017-02-28 20:47:35

标签: ruby-on-rails ruby scope pundit

我已经尝试了3年,学习如何在我的Rails应用程序中使用pundit。

我有一个提案模型,我试图用它来显示基于我试图在解决方法中定义的一组规则的提案索引。

我的最新尝试如下。

class ProposalPolicy < ApplicationPolicy


  class Scope < Scope

    def resolve
                      # find all proposals where the user created the proposal;
      proposal_ids =  user.proposal_ids +
                      # all where the user has the reviewing role at the creator's organistion - if the proposal is in scope 'reviewable'; and
                      Proposal.reviewable.for_reviewer(user).pluck(:id) +
                      # all where the proposal is openly published;
                      Proposal.openly_published.pluck(:id) +
                      # all where the user is invited;
                      Proposal.published_to_invitees.invited(user).pluck(:id) +
                      # all where the user is a counterparty and the proposal is published to counterparties
                      Proposal.published_to_counterparties.counterparty(user).pluck(:id)
      Proposal.where(id: proposal_ids)
    end
  end

在我的proposal.rb中,我已经定义了我在上面的方法中使用的范围:

class Proposal < ApplicationRecord
  scope :reviewable,  -> { in_state(:under_review) }
  scope :openly_published, -> { in_state(:publish_openly) }
  scope :for_reviewer, -> (user){where(user.has_role?(:consents, @matching_organisation)) }
  scope :published_to_invitees, -> { in_state(:publish_to_invitees) }
  scope :invited,     -> (user){ where(invitee_id: user.id) }
  scope :published_to_counterparties, -> { in_state(:published_to_counterparties_only) }
  scope :counterparty, -> (user){ where( user_id: @eligible_user)}
  scope :proponent,   ->(user){ where(user_id: user.id) }

  def matching_organisation
    @proposal.user.organisation_id == @reviewer.organisation.id
  end
end

我尝试这个时没有出现任何错误,但实际上并没有用。如果我创建一个新提案,那么我应该能够在我的索引中看到该提议,因为我满足了我的resolve方法中的第一条规则,但我得到了一个空的结果索引。

我是否可以通过尝试编写可以采用多种标准的解决方法来查看我出错的地方?

1 个答案:

答案 0 :(得分:0)

很难从这个代码示例中分辨出它可能会崩溃的地方。我的建议是为每个范围和matching_organization方法设置测试方案。

如果还没有,请为每个范围创建一个测试。

describe Proposal do
  it 'matching_organisation should return the expected organization'
    assert_equal @expected_org, @proposal.matching_organisation
  end
  describe 'scopes' do
    test 'reviewable' do
      assert_equal @expected, Proposal.reviewable
    end
    test 'for_reviewer' do
      assert_equal @expected, Proposal.for_reviewer(@user)
    end
    # etc...
  end
end

一旦确定您的班级范围和方法是正确的,您就可以创建政策测试:

# test/policies/proposal_policy_test.rb
describe ProposalPolicy do
  describe 'scope' do
    it 'must include expected policy' do
      policy_scope(Proposal).must_include(@expected_policy)
    end
    it 'wont include unexpected policy' do
      policy_scope(Proposal).wont_include(@unexpected_policy)
    end
  end
end

(使用MiniTest::Spec语法显示的示例)