Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create join table with no primary key

I have two tables with a many to many relationship that I am using has_and_belongs_to_many to define the association.

class Foo < ActiveRecord::Base
  ...
  has_and_belongs_to_many :bar
  ...
end

class Bar < ActiveRecord::Base
  ...
  has_and_belongs_to_many :foo
  ...
end

I also have the class defined to represent the join table

class BarFoo < ActiveRecord::Base
  ...
  belongs_to :foo
  belongs_to :bar
  ...
end

When I run rake db:seed I get the following error:

Primary key is not allowed in a has_and_belongs_to_many join table (bar_foo)

If I edit the database and remove the primary key field (ID) from the bar_foo table and then rerun rake db:seed everything works as desired.

Given the above, what is the preferred means of creating join tables in rails with no primary key?

I also tried using "has_many :bars, :through => :foo" and vise versa but got an error message something like "undefined method 'klass' for nil:NilClass".

like image 222
Keith Avatar asked Oct 22 '10 14:10

Keith


People also ask

Can I join table without primary key?

Yes, you can! The longer answer is yes, there are a few ways to combine two tables without a common column, including CROSS JOIN (Cartesian product) and UNION. The latter is technically not a join but can be handy for merging tables in SQL. In this article, I'll guide you through the different solutions with examples.

Is foreign key needed for join?

A declared foreign key relationship is not necessary for using join . Foreign keys are not needed to join tables!

Can you only join on primary keys?

A primary key is a value that cannot be duplicated within a table. This means that one value can only be seen once within the primary key column.


1 Answers

You don't need the model

class BarFoo < ActiveRecord::Base
  ...
  belongs_to :foo
  belongs_to :bar
  ...
end

the has_and_belongs_to_many association will search for a table called bar_foo in your database what you need to do is generate a migration to create this table.

rails generate migration add_table_bar_foo_for_association

then you edit your migration and it should look like this

class AddTableBarFooForAssociation < ActiveRecord::Migration
  def up
    create_table :bar_foo, :id => false do |t|
        t.references :bar
        t.references :foo
    end
  end

  def down
    drop_table :bar_foo
  end
end

Now your association should work and also if you need the association to have extra attributes on the join you can use the has_many :through way and create a model associated to this.

like image 182
Mr_Nizzle Avatar answered Nov 16 '22 23:11

Mr_Nizzle