所以,经过一段时间的思考后,我不知道对此进行建模的正确方法是什么。
我有一个专注于分享图片的网站。为了让用户满意,我希望他们能够订阅许多不同的图像集。
到目前为止,有两种类型的集合。一个是"创作者"关系,定义了处理特定图像的人。看起来像这样:
class Image < ActiveRecord::Base
has_many :creations
has_and_belongs_to_many :locations
has_many :creators, through: :creations
end
class Creator < ActiveRecord::Base
has_many :images, ->{uniq}, through: :creations
has_many :creations
belongs_to :user
end
class Creation < ActiveRecord::Base
belongs_to :image
belongs_to :creator
end
用户还可以使用主观标记标记图像,这是图像中不客观存在的标记。典型的主观标签包括&#34;搞笑&#34;或者&#34;伤心,&#34;那种东西。这样实现了:
class SubjectiveTag < ActiveRecord::Base
# Has a "name" field. The reason why the names of tags are a first-class DB model
# is so we can display how many times a given image has been tagged with a specific tag
end
class SubjectiveCollection < ActiveRecord::Base
# Basically, "User X tagged image Y with tag Z"
belongs_to :subjective_tag
belongs_to :user
has_many :images, through: :subjective_collection_member
end
class SubjectiveCollectionMember < ActiveRecord::Base
belongs_to :subjective_collection
belongs_to :image
end
我希望用户能够订阅Creators和SubjectiveTags,并在他们登录时在主页上按顺序显示这些集合中的所有图像。
最好的方法是什么?我应该拥有一堆不同的订阅类型 - 例如,一个名为SubjectiveTagSubscription
,一个名为CreatorSubscription
?如果我这样做,那么检索每个集合中所有图像的最有效方法是什么?
答案 0 :(得分:1)
您想要使用的是Polymorphic Association。
在您的情况下,它看起来像这样:
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :subscribeable, polymorphic: true
end
subscriptions
表需要包含以下字段:
user_id
(整数)subscribeable_id
(整数)subscribeable_type
(字符串)此设置将允许订阅引用任何其他模型的实例,因为ActiveRecord将使用subscribeable_type
字段来记录所订阅事物的类名。
要为当前登录的用户生成图像列表,您可以执行以下操作:
Subscription.where(user_id: current_user.id).map do |subscription|
subscription.subscribeable.images.all
end.flatten
如果上述方法的性能影响是不可容忍的(每个订阅一个查询),您可以通过STI将这两种类型的可订阅者折叠成一个表(这在这里看起来不是一个好主意,因为两个表格不是很相似)或者您可以回到最初的建议,即拥有两种不同类型的订阅模型/表格,分别查询每个订阅模型/表格。