在Rails中建模订阅

时间:2014-10-19 17:26:37

标签: ruby-on-rails ruby database rails-activerecord

所以,经过一段时间的思考后,我不知道对此进行建模的正确方法是什么。

我有一个专注于分享图片的网站。为了让用户满意,我希望他们能够订阅许多不同的图像集。

到目前为止,有两种类型的集合。一个是"创作者"关系,定义了处理特定图像的人。看起来像这样:

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?如果我这样做,那么检索每个集合中所有图像的最有效方法是什么?

1 个答案:

答案 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将这两种类型的可订阅者折叠成一个表(这在这里看起来不是一个好主意,因为两个表格不是很相似)或者您可以回到最初的建议,即拥有两种不同类型的订阅模型/表格,分别查询每个订阅模型/表格。