# Patients and ContactPerson as an STI (after discussion)
### Business objectives
- retain information about patient-to-contact-person relationship
- retain info about what type of contact-person is it? Legal guardian? Ordinary fella of convenience?
## Solution
```plantuml
@startuml
class ContactLink {
+ person
+ contact
+ legal_guardian: bool
}
class Person <<Abstract>> {}
package Contacts #0F0 {
class Patient {
+ contacts[]
}
class ContactPerson {
+ phone_number
}
Person o-- ContactPerson
Person o-- Patient
}
Person }|--|| ContactLink
note left on link
<b>Join table</b>
ContactPerson should not
have contact_links,
only Patient can have contact_links :-)
end note
Patient ||--|{ ContactLink
note top of Person #0F0: STI
@enduml
```
Validatin
## Todos
- [ ] 1. Create Person as an STI with ContactPerson, and Patient subclasses
- [ ] Migration
- [x] rename `patients` table to `persons`
- [x] add non-null type column and prefill with `Person` val for compatibility
- [ ] backfill/mass create ContactPersons from Bookings already in DB
- [ ] Models & Validations
- [x] 2. Create JOIN table `contact_links` table
- [x] adjust associations
- [ ] 3. controllers/services
- [ ] pass contact persons to Views to populate dropdown and stuff
- [ ] on form submit
- [ ] create contact persons when applicable
- [ ] store patient-contact-person associations
```ruby =
class CreateContactLinks < ActiveRecord::Migration[6.0]
def change
create_table :contact_links do |t|
t.references :person_id, foreign_key: { to_table: 'persons' }
t.references :contact_id, foreign_key: { to_table: 'persons' }
t.boolean :legal_guardian
end
end
end
# add_reference :contact_links, :persons, foreign_key: true
end
```
```ruby=
class Person < ActiveRecord::Base
include SanitizePhoneNumber
end
class Patient < Person
validates :national_id, length: {is: 11, message: :wrong_length_digit}, allow_blank: true
has_many :contact_links
has_many :contacts, through :contact_links # better name appreciated! [ContactPerson, Patient]
scope :
# all that was already
has_one :user
has_many :pat_links
has_many :users, through: :pat_links, source: :pat_linkable, source_type: 'User'
has_many :referrals, through: :pat_links, source: :pat_linkable, source_type: 'Referral'
has_many :booking_bases, class_name: 'BookingBase', through: :pat_links, source: :pat_linkable, source_type: 'BookingBase'
encrypts :national_id
before_validation do
self.independent = !contacts.legal_guardians.any?
end
# sync independent|dependent state on_create,on_update
# validate_dependency_state # not a priority, likely many PROD DB records invalid in that regard
# scope :independent, -> { joins(:responsible_contacts).where(responsible_contacts: {legal_guardians: true})}
# scope :dependent, -> { joins(:responsible_contacts).where(responsible_contacts: {legal_guardians: false})}
# def independent?
# responsible_contacts.legal_guardians.any?
# end
# def dependent?
# !independent?
# end
end
class ContactLink < ActiveRecord::Base
belongs_to :patient
belongs_to :contact
scope :legal_guardians, -> { where(legal_guardian: true) }
# handle destroy case on both ends
end
class ContactPerson < Person
has_many :contact_links
has_many :contact_linkees, through: :contact_links # better name appreciated!
end
```