The has_many => :through association joins two models through a third, allowing additional join information to be stored in the third model. In the example from Rails Guides: Association Basics, the physician and patient models are joined through an appointment model.
1. The Migration
Assuming the two resource models are already created, now create the join table:
def change
create_table :appointments do |t|
t.integer :physician_id
t.integer :patient_id
t.timestamps
end
add_index :appointments, :physician_id
add_index :appointments, :patient_id
add_index :appointments, [:physician_id, :patient_id], :unique => true
end
end
The add_index lines make it faster to access information via the join model by instructing Rails to create an index to refer to. The last line includes :unique => true to ensure that there can only be one record joining each patient to each physician.
Migrate up:
2. The Models
The following code will set up the association:
has_many :appointments
has_many :patients, :through => :appointments
end
belongs_to :physician
belongs_to :patient
end
has_many :appointments
has_many :physicians, :through => :appointments
end
:dependent => :destroy
Add :dependent => :destroy to the join model to destroy its records when a record from either of the two joined models is destroyed. Here, destroying a physician will remove all of its appointments. This action will NOT remove patients.
accepts_nested_attributes_for
Add accepts_nested_attributes_for to any model to allow another model to be edited via its views. Here, patients can be created from the physician view.
3. The View
The following line within the patient form will automatically create a select box listing all physicians. Selecting one will create a join record in the appointments table. (Uses Formtastic syntax.)
.
.
<%= f.input :physicians, :as => :select %>
