Rails N:M
Last updated
Last updated
Implement many to many relationships through models in Rails
Describe the model ordering opinion used by Rails
Use the collection_check_boxes
form helper to display a collection of associated items
Today we'll add rangers to the national park app using a many to many relationship.
Models
Park
Ranger
ParksRangers (join table)
Association
Park <-> ParksRangers <-> Ranger
Park has_and_belongs_to_many
Rangers
Ranger has_and_belongs_to_many
Parks
Views
parks#edit - add/remove rangers checkboxes
parks#new - add/remove rangers checkboxes
rangers#show
list all parks with a specific ranger
Review of Parks
Rangers
ParksRangers
The join table with the two models must be plural and in alphabetical order if you want to follow the Rails convention. Also, --force-plural
is needed so that the table will never be pluralized.
Note that if you want to name your join table something different, you can specify your own join model with through:
When you do :references
it automatically creates the belongs_to
relations on the join table, but we need to manually add the has_and_belongs_to_many
to the ranger and park models.
models/park.rb
models/ranger.rb
When creating the M:M associations, the name of the model is pluralized when adding the has_and_belongs_to_many
method. In ParksRangers, the associations will be singular and generated for you.
Because Park and Ranger reference each other with has_and_belongs_to_many
they can reference each other.
Basic Examples
Advanced Examples / chaining
Add checkboxes to the form
:ranger_ids
refers to the model's rangers
@rangers
refers to all the rangers available (pass from the controller Ranger.all
)
:id
refers to the value of the checkbox
:name
refers to the label of the checkbox
That's it! As far as assigning the rangers in the controller, we can modify the Park
model to accept the ranger_ids
array like so:
In order for the rangers to be assigned automatically, we can add the accepts_nested_attributes_for
method to the Park
model. You'll also want to add inverse_of:
to the park's ranger association, in order to run any validations that may be on the Ranger
model.
When showing a specific ranger, display the ranger name and the list of parks associated with it.