Подтвердить что ты не робот

Создать таблицу соединений без первичного ключа

У меня есть две таблицы со многими отношениями, которые я использую has_and_belongs_to_many для определения ассоциации.

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

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

У меня также есть класс, определенный для представления таблицы соединений

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

Когда я запускаю rake db: seed, я получаю следующую ошибку:

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

Если я отредактирую базу данных и удалю поле первичного ключа (ID) из таблицы bar_foo, а затем повторно запустил rake db: seed все будет работать по желанию.

Учитывая вышеизложенное, каково предпочтительное средство создания таблиц объединения в рельсах без первичного ключа?

Я также попытался использовать "has_many: bars,: through = > : foo" и наоборот, но получил сообщение об ошибке "undefined метод" класс "для nil: NilClass".

4b9b3361

Ответ 1

Да, первичный ключ не разрешен для has_and_belongs_to_many.

У вас есть 2 способа решить эту проблему:

Удалите первичный ключ в этой таблице. В вашем классе миграции:

create_table :bar_foo, :id => false do |t|
  t.integer :bar_id
  t.integer :foo_id
end

Кроме того, вам нужно будет удалить файл bar_foo.rb из app/models, а также удалить любые файлы и тестовые файлы, которые могли быть сгенерированы. Хорошей идеей является вызов script/destroy (или rails destroy) для уничтожения файлов, а затем восстановления миграции.

Или преобразовать в has_many :through

class Foo < ActiveRecord::Base
  ...
  has_many :bar_foos
  has_many :bars, :through => :bar_foos
  ...
end

class Bar < ActiveRecord::Base
  ...
  has_many :bar_foos
  has_many :foos, :through => :bar_foos
  ...
end

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

Ответ 2

Если вы хотите использовать ассоциацию HABTM, вы не должны создавать для нее модель - просто таблицу bars_foos с столбцами bar_id и foo_id integer.

Если вам нужна модель между ними (например, если вы хотите отслеживать created_at или некоторые другие атрибуты отношения), вы можете добавить дополнительную модель, например. Barred, а затем у вас будет:

class Foo < ActiveRecord::Base
  ...
  has_many :bars, :through => :barred
  ...
end

class Bar < ActiveRecord::Base
  ...
  has_many :foos, :through => :barred
  ...
end

class Barred < ActiveRecord::Base
  has_many :bars
  has_many :foos
end

Ответ 3

Вам не нужна модель

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

ассоциация has_and_belongs_to_many будет искать таблицу с именем bar_foo в вашей базе данных, что вам нужно сделать, это создать миграцию для создания этой таблицы.

рельсы создают миграцию add_table_bar_foo_for_association

то вы редактируете свою миграцию, и она должна выглядеть так:

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

Теперь ваша связь должна работать, а также если вам нужна ассоциация для добавления дополнительных атрибутов в соединение, вы можете использовать способ has_many :through и создать модель, связанную с этим.