In One of my project, we had Many to Many association between models. this allowed me to look more deeply into the has_and_belongs_to_many(HABTM) association.
When we say:
class Movies < ActiveRecord::Base
has_and_belongs_to_many :gallery_photos, :join_table=> "movies_gallery_photos"
class GalleryPhoto < ActiveRecord::Base
has_and_belongs_to_many :movies, :join_table=>"movies_gallery_photos"
Rails will assume there is a table “movies_gallery_photos” that include foreign keys to the two entities. So this table should be created by the following migration
create_table :movies_gallery_photos, :id => false do |t|
t.integer :movie_id, :null => false
t.integer :gallery_photo_id, :null => false
:id=>false will prevent the creation of the default primary key for that table.
as the API documentation say; other attributes in that relation will be loaded with the objects and will be read only, including the :id. So failing to disable the id generation for that table will cause the loaded objects to have and “id” attribute holding the value of the id or the movies_gallery_photos entries instead of the ids of the target entity (movies or gallery_photos here).
Having (:id) false helps to over Mysql::Error: Duplicate entry ‘#’ for key #” entry error we faces while adding entries. (movie.gallery_photos << photo). But it leads to creation and availability of duplicate values in the movies_gallery_photos table. i.e.
movies.gallery_photos << photos
will not check for uniqueness of the photos objects.