所以目前我有一个类别和一个文章模型:
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
我想知道,不是为每个模型创建新的联接表,而是可以共享一个联接表吗?还是这实际上是更可取的方法,如果可以,为什么?
使用polymorphic associations。但这不适用于has_and_belongs_to_many
,因此我们需要手动设置多对多关系。参见this answer for more。
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
来存储关系的ID和类。 categorable_type: 'Article', categorable_id: 5
引用ID为5的文章。
由于是多对多,因此无需修改articles
表或projects
表。
多态关联很方便,但是由于它不使用外键,因此数据库无法强制执行参照完整性。这是由Rails处理的。这在Rails应用程序中是可以接受的,因为数据库通常仅由Rails模型控制。 Rails模型和数据库可以视为一个单元。