Skip to content

Create Strong Habtm Relationships

How to create a strong has and belongs to many relationship

Section titled “How to create a strong has and belongs to many relationship”

When creating has and belongs to many relationship in Rails, the best practice is as follow:

For this example, i have dogs and toys

create_join_table :dogs, :toys do |t| t.references :dogs, index: true, foreign_key: true, foreign_key: { on_delete: :cascade } t.references :toys, index: true, foreign_key: true, foreign_key: { on_delete: :cascade } end

This creates our join table but also postgresql foreign keys, prevents invalid values from getting in and if the dogs or toys records are deleted, it cleans up after itself and remove the record from the join table.

The name of your join table should be conventionally by alphabetical order of the models. Since dogs is before toys the table is then going to be dogs_toys both pluralized.

Create an unique constraint to prevent duplicates:

Section titled “Create an unique constraint to prevent duplicates:”

execute “ALTER TABLE dogs_toys ADD CONSTRAINT unique_dog_toys UNIQUE (dog_id, toy_id);“

Update your model to cleanup any invalid inbound values:

Section titled “Update your model to cleanup any invalid inbound values:”

In dogs:

normalize :toys_ids

In toys:

normalize :dogs_ids

The excellent select2 js library will delivery a rich interface to modify the records in a relationship. It’s enabled by default in crm so you just add select2 to your css class for your inputs. The input needs to be a of type hidden

<%= f.hidden_field :dogs_ids, class: "select2", data: { choices: options_to_select2_choices(f.object.list_of_dogs), multiple: true, placeholder: "Choose dog breed" } %>