0

I have a model called dispatch with is a join table that relates two other models, referral requests and clinicians. In my application, a staff user will create a referral request record which houses some details about what their patient is looking for. Some unbuilt logic will find all the clinician users who match at least one insurance stated in the patient record, and that will result in sending a mailer to each of these clinicians. The dispatch model is how I am attempting to record the relationships between referral requests and clinicians, so I know which clinicians received emails and also so I can record their responses (yes or no).

Clinicians also belong to markets, and staff belong to universities which belong to markets.

Each clinician has a clinician profile, and in addition to clincian_profiles table there is a clinician_profiles_insurances table so I can call .clinician_profile.insurances on a given user who is a clinician and return all the insurances they take.

On a given referral request I can also call .insurances to show all the insurances that a patient has.

I am trying to use a Pundit policy scope within the dispatch new method to do the following:

-only show clinician users who are in the same market as the staff user's university.

-only show clinician users who have at least one matching insurance with the referral request.

Here is my best swipe so far, which does not even work for restricting the scope of the markets. What am I doing wrong?

Dispatch Policy

    class DispatchPolicy < ApplicationPolicy
  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve

      if user.admin?
        scope.all
      else
        scope.joins(:clinician).merge(User.where(market: user.market))
      end
    end
  end

My users have multiple roles:

enum role: { staff: 0, clinician: 1, admin: 2 }

Here are the relationships:

class Dispatch < ApplicationRecord
    belongs_to :referral_request
    belongs_to :clinician, class_name: 'User', foreign_key: 'user_id'

class ReferralRequest < ApplicationRecord
  belongs_to :user, -> { where role: :staff }
  has_many :dispatches
  has_many :clinicians, through: :dispatches

module StaffUser
  extend ActiveSupport::Concern

  included do
    belongs_to :university
    has_many :patients
    has_many :referral_requests
    validates :university_id, presence: true, if: :staff?
  end

Here is my new method in the Dispatches controller:

def new
@clinicians = policy_scope(Dispatch)
@dispatch = @referral_request.dispatches.new
end

Here is the table in dispatches/new.html.erb where I am trying to show all users who

1) are clinicians 2) belong to the same market as the staff user's university 3) have at least one insurance in their clinician profile that matches an insurance associated with the referral request.

<% @clinicians.each do |clinician| %>
  <tr>
    <td><%= clinican.id %></td>
    <td><%= clinican.name %></td>
    <td><%= clinican.market.name %></td>
    <td><%= clinican.clinician_profile.insurances.map(&:name).to_sentence %></td>
    <td><%= clinican.clinician_profile.genders.map(&:name).to_sentence %></td>
    <td><%= clinican.clinician_profile.races.map(&:name).to_sentence %></td>
    <td><%= clinican.clinician_profile.languages.map(&:name).to_sentence %></td>
  </tr>
<% end %>
</tbody>
</table>

Insurance model:

class Insurance < ApplicationRecord
    has_and_belongs_to_many :patients
    has_and_belongs_to_many :clinician_profiles
    has_and_belongs_to_many :markets
end

Patient model

class Patient < ApplicationRecord
  belongs_to :author, -> { where role: :staff }, class_name: 'User', foreign_key: 'user_id'

  has_and_belongs_to_many :genders
  has_and_belongs_to_many :concerns
  has_and_belongs_to_many :insurances
  has_and_belongs_to_many :races
  has_many :referral_requests
  belongs_to :staff_doctor, class_name: 'User', foreign_key: 'staff_doctor_id'

  def has_referral?
    !self.referral_requests.empty?
  end
end

**Clinician concern**
require 'active_support/concern'

module ClinicianUser
  extend ActiveSupport::Concern

  included do
    has_one :clinician_profile
    has_many :lists
    has_many :universities, through: :lists
    has_many :dispatches
    has_many :referral_requests, through: :dispatches
    after_create :create_clinician_profile
    belongs_to :market
    validates :market_id, presence: true, if: :clinician?
  end

  class_methods do
  end
end

Staff Concern

require 'active_support/concern'

module StaffUser
  extend ActiveSupport::Concern

  included do
    belongs_to :university
    has_many :patients
    has_many :referral_requests
    validates :university_id, presence: true, if: :staff?
  end

  class_methods do
  end
end

Clinician Profile Model

class ClinicianProfile < ApplicationRecord
  belongs_to :user, -> { where role: :clinician }
  has_and_belongs_to_many :languages
  has_and_belongs_to_many :races
  has_and_belongs_to_many :insurances
  has_and_belongs_to_many :genders
end

Am I even thinking about this the right way? Is a pundit policy a good solution for all or part of what I am trying to do? Thanks for all feedback. I'm clearly a bit lost.

mike9182
  • 269
  • 1
  • 3
  • 17

1 Answers1

0

Why not solve one issue at a time?

Ignore Pundit for now and come up with a ActiveRecord query that returns what you expect.

user = User.where(role: :staff).first
Dispatch.joins(:clinician).merge(User.where(market: user.market))

This joins "clinician".. which I believe is actually "Users" table behind the scenes because of "class: User" in the model. This query seems fine for parts 1 and parts 2.

Running that AR query, should first join all dispatches with users, and select only the dispatches that have same 'market' as the "current user" passed into the policy.

But remember:

@clinicians = policy_scope(Dispatch)

is returning dispatches, not "clinicians" (Users), so in the code you wrote, "clinicians.id" would be the dispatch table id which is what you don't want? Unless I'm mistaken.

Try and get part 1 and 2 working first if it's not already working.

Part 3 "have at least one insurance in their clinician profile that matches an insurance associated with the referral request."

Sounds like you're going to have to join also on "referral requests", and do more SQL, I just don't know how insurance is figured out in your domain (is it has_many :insurance_plans etc, that would require more info)

jeremy04
  • 314
  • 1
  • 3
  • thanks for this helpful feedback. when I assign user as you suggest and then run the second line in console, it runs but returns empty. user.market returns Boston, which is id:2. I have clinicians in the db who belong to Boston. I may be misunderstanding, but it seems to me that the query you wrote searches for and returns dispatches, but I think what I want to return is a list of clinicians. I very well may be missing something, so please let me know what you think. – mike9182 Oct 11 '17 at 17:15
  • I added the additional models for insurance etc. so you could see them. – mike9182 Oct 11 '17 at 17:21