I am a newbie to rails. I wanted to try out has_many through association with the following example.
Relation: Operation_doctors can only make an appointment with operation patients and vice versa. Same applies for treatment doctors.
Doctor.rb
class Doctor < ActiveRecord::Base
has_many :appointments
has_many :operation_patients, :class_name => 'Patient', :source => :operation_patient ,through: :appointments
has_many :treatment_patients, :class_name => 'Patient', :source => :treatment_patient ,through: :appointments
end
Patient.rb
class Patient < ActiveRecord::Base
has_many :appointments
has_many :operation_doctors,:class_name => 'Doctor', :source => :operation_doctor,through: :appointments
has_many :treatment_doctors,:class_name => 'Doctor', :source => :treatment_doctor,through: :appointments
end
Appointment.rb
class Appointment < ActiveRecord::Base
belongs_to :operation_doctor, :class_name => 'Doctor', :foreign_key => :operation_doctor
belongs_to :treatment_doctor, :class_name => 'Doctor', :foreign_key => :treatment_doctor
belongs_to :operation_patient, :class_name => 'Patient', :foreign_key => :operation_patient
belongs_to :treatment_patient, :class_name => 'Patient', :foreign_key => :treatment_patient
end
Error in Rails console: Input:
@op1 = Patient.new
@od1 = Doctor.new
Error:
irb(main):023:0> @op1.operation_doctors << @od1
(0.1ms) begin transaction
(0.1ms) rollback transaction
ActiveRecord::UnknownAttributeError: unknown attribute 'patient_id' for Appointment.
In patient.rb
class Patient < ActiveRecord::Base
has_many :appointments
For this to work, you need a patient_id
field on the Appointment table. Your actual appointment relation is more complex. There are 2 ways for resolving the error.
class Patient < ActiveRecord::Base
has_many :operation_appointments, :class_name => 'Appointment', :foreign_key => :operation_patient
has_many :treatment_patients, :class_name => 'Appointment', :foreign_key => :treatment_patient
You will need to do the same thing for the doctor's model.
I would be inclined to make a larger datamodel for this solution. Since you know that doctors have two types and patients have two types, they are incompatible with each other, and they have logic that would be duplicate, I would lean on inheritance.
Here's a sketch of my data model:
ActiveRecord::Base
Doctor Patient Appointment
OperationDoctor OperationPatient OperationAppointment
TreatmentDoctor TreatmentPatient TreatmentAppointment
The Appointment table would contain a doctor_id, patient_id, and type field
rails g model appointment type:string patient:references doctor:references
rails g model operation_appointment --parent appointment
This would simplify the classes:
# appointment.rb
belongs_to :patient
belongs_to :doctor
# patient.rb
has_many :appointments
has_many :doctors, :through => :appointment
This way your doctor would either be a TreatmentDoctor or a OperationDoctor, and you can use validation on those models to ensure the patient is of the correct type.