лучший способ поделиться has_and_belongs_to_many между несколькими роторами - PullRequest
1 голос
/ 25 января 2020

Так что в настоящее время у меня есть категория и модель статьи:

class Article < ApplicationRecord
  has_and_belongs_to_many :categories
end

class Category < ApplicationRecord
end

, которая отлично работает. Но теперь я хочу расширить систему и представить другие модели, которым также будут назначены категории аналогичным образом, например:

class Article < ApplicationRecord
  has_and_belongs_to_many :categories
end

class Project < ApplicationRecord
  has_and_belongs_to_many :categories
end

Мне интересно, а не создавать новые таблицы соединений для каждой модели, не так ли можно поделиться одной таблицей соединений? Или это на самом деле более предпочтительный подход, и если да, то почему?

1 Ответ

2 голосов
/ 25 января 2020

Используйте polymorphi c ассоциаций . Но это не работает с has_and_belongs_to_many, поэтому нам нужно установить отношение «многие ко многим» вручную. См. этот ответ для получения дополнительной информации .

class Category < ApplicationRecord
  has_many :category_relations
end

class CategoryRelation < ApplicationRecord
  belongs_to :categories
  belongs_to :categorable, polymorphic: true
end

class Article < ApplicationRecord
  has_many :category_relations, as: categorable
  has_many :categories, through: :category_relations
end

class Project < ApplicationRecord
  has_many :category_relations, as: categorable
  has_many :categories, through: :category_relations
end

И миграция будет выглядеть примерно так ...

class CreateCategorable < ActiveRecord::Migration[5.2]
  def change
    create_table :categories do |t|
      t.string :name
      t.timestamps
    end

    create_table :categories_relations, id: false do |t|
      t.references :categories, index: true
      t.references :categorable, polymorphic: true, index: true
    end
  end
end

t.references :categorable, polymorphic: true, index: true - это удобный метод, который устанавливает t.bigint :categorable_id и t.string :categorable_type для хранения идентификатора и класса отношений. categorable_type: 'Article', categorable_id: 5 ссылается на Статью с идентификатором 5.

Так как это множество ко многим, никаких модификаций для таблиц articles или projects не требуется.

Polymorphi c ассоциации удобны, но поскольку база данных не использует внешние ключи, база данных не может обеспечить ссылочную целостность. Это обрабатывается Rails. Это приемлемо в приложении Rails, поскольку база данных обычно контролируется только моделью Rails. Модель Rails и базу данных можно рассматривать как единое целое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...