0

I have been trying for 3 years to learn how to use pundit with my Rails app.

I have a proposal model, that I'm trying to use to show an index of proposals based on a set of rules that I'm trying to define in a resolve method.

My latest attempt is below.

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

In my proposal.rb, I have defined the scopes that I use in the above method:

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

I don't get any errors when I try this, but it actually doesnt work. If I create a new proposal then I should be able to see that proposal in my index because I satisfy the first rule in my resolve method, but I get an empty index of results.

Can anyone see where I'm going wrong with my attempts to write a resolve method that can take a number of criteria?

Ryenski
  • 9,582
  • 3
  • 43
  • 47
Mel
  • 2,481
  • 26
  • 113
  • 273
  • What is `@proposal` in the `matching_organization` method? Is that supposed to be `self`? There are no arguments on that method - where are `@proposal` and `@reviewer` coming from? – Ryenski Feb 28 '17 at 21:09

1 Answers1

0

It's really difficult to tell from this code sample where it might be breaking down. My recommendation would be to set up a test scenario for each one of these scopes and for the matching_organization method.

If you haven't already, create a test for each scope.

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

Once you're sure your class scopes and methods are correct, you can create a policy test:

# 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

(examples shown using MiniTest::Spec syntax)

Ryenski
  • 9,582
  • 3
  • 43
  • 47