Создать таблицу соединений без первичного ключа
У меня есть две таблицы со многими отношениями, которые я использую 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".
Ответы
Ответ 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
и создать модель, связанную с этим.