I am attempting to add a uniqueness constraint to my database to stop duplicate entries being added to a join table. However, it does not seem to be working. I do not have a model for the join table, so I am not adding model level validations.
Here is the migration:
class CreateBreedsAndTags < ActiveRecord::Migration[5.1]
def change
create_table :breeds do |t|
t.string :name, unique: true, present: true
t.timestamps
end
create_table :tags do |t|
t.string :name, unique: true, present: true
t.timestamps
end
create_join_table :breeds, :tags do |t|
t.integer :breed_id
t.integer :tag_id
t.index [:breed_id, :tag_id], unique: true
end
end
end
The Breed and Tag models are both very simple, and they use has_and_belongs_to_many
because I wanted to test out the association. I could add add -> { distinct }
to the association, but I would like to stop duplicates from being created in the first place.
class Breed < ApplicationRecord
# Some validations and stuff here
has_and_belongs_to_many :tags
end
If I create a Breed and Tag in the rails console. I can do something like this even though there is a database level unique constraint on the join table:
b = Breed.create(name: 'b')
t = Tag.create(name: 't')
b << t
b << t
b.save!
b.tags # outputs the same tag multiple times
EDIT:
1) It's worth noting that I found this stack overflow which recommends overriting the <<
in the association. However, this doesn't explain why my unique constraint is failing.
2) I also found this stack overflow which recommends a db level constraint, but that is not working for me.
EDIT2:
Here is some table information from the database:
table_name | index_name | column_name
-------------------------+-----------------------------------------+-----------------
ar_internal_metadata | ar_internal_metadata_pkey | key
breed_tags | breed_tags_pkey | id
breeds | breeds_pkey | id
breeds_tags | index_breeds_tags_on_breed_id | breed_id
breeds_tags | index_breeds_tags_on_tag_id | tag_id
And I ran a \d breeds_tags
Table "public.breeds_tags"
Column | Type | Modifiers
----------+--------+-----------
breed_id | bigint | not null
tag_id | bigint | not null
Indexes:
"index_breeds_tags_on_breed_id" btree (breed_id)
"index_breeds_tags_on_tag_id" btree (tag_id)