2

I created a many-to-many relationship in rails, here's my models and migrations

class Channel < ActiveRecord::Base
  has_and_belongs_to_many :packages
  validates_presence_of :name
end

class Package < ActiveRecord::Base
  has_and_belongs_to_many :channels
  validates_presence_of :name
end

class CreateChannelsPackages < ActiveRecord::Migration
  def change
    create_table :channels_packages, :id => false do |t|
      t.references :channel
      t.references :package

      t.timestamps
    end
    add_index :channels_packages, :channel_id
    add_index :channels_packages, :package_id
  end
end

Then i have a multiple select, but when i try to save i get this error

SQLite3::ConstraintException: constraint failed: INSERT INTO "channels_packages" ("package_id", "channel_id") VALUES (1, 1)

I tried to remove the indexes from the migration but it didn't solve it, did somebody else have this problem?

Btw i'm using Rails 3.2.6 and sqlite3 1.3.6

Rogerio Chaves
  • 2,719
  • 2
  • 25
  • 24

2 Answers2

2

I think gabrielhilal's answer is not quite correct: use of extra attributes in the join table is deprecated, thus you need to remove the timestamp in your migration, then it should work just fine with the has_and_belongs_to_many wich itself is not deprecated.

If you do need additional attributes in your join table, though, has_many :through is the way to go.

There is also another question with good answers on this topic: Rails migration for has_and_belongs_to_many join table

Community
  • 1
  • 1
bento
  • 2,079
  • 1
  • 16
  • 13
1

I don't know if it is the reason of your problem, but the has_and_belongs_to_many association is deprecated.

According to the Rails Guide:

The use of extra attributes on the join table in a has_and_belongs_to_many association is deprecated. If you require this sort of complex behavior on the table that joins two models in a many-to-many relationship, you should use a has_many :through association instead of has_and_belongs_to_many.

I know that you are not adding any extra attribute to the join table, but try changing your migration to the below, which I think is the default:

class CreateChannelPackageJoinTable < ActiveRecord::Migration
  def change
    create_table :channels_packages, :id => false do |t|
      t.integer :channel_id
      t.integer :package_id

      t.timestamps
    end
  end
end
gabrielhilal
  • 10,660
  • 6
  • 54
  • 81
  • thanks, using has_many :through instead of has_and_belongs_to_many worked, though has_and_belongs_to_many works normally on mysql. The migration had nothing to do with it, i could use .references and add_index normally – Rogerio Chaves Jul 03 '12 at 02:02