【发布时间】:2015-09-18 18:45:20
【问题描述】:
我想对我正在尝试建模的活动提要提出第二意见。我想出了三种方法。
我有一个 Project、Membership、Bucket、Upload 和 Document 模型,它们都是 ActiveRecord 模型。一个项目有许多成员和许多桶。一个bucket有很多uploads,一个uploads有很多documents。我想跟踪成员资格、存储桶、上传和文档(更新、删除、创建等)的活动。
class Project
has_many :memberships
has_many :buckets
has_many :documents, through: :buckets
end
class Bucket
belongs_to :project
has_many :uploads
has_many :documents, through: :uploads
end
class Upload
belongs_to :bucket
has_many :documents
end
class Document
belongs_to :upload
end
这本身相当容易。但有些存储桶是私有的,只有管理员才能看到。这意味着他们的活动以及他们上传的活动和他们的文档只能对管理员可见。
方法一:多态Activity类
Activity 属于可跟踪对象,在本例中为 Membership、Document、Upload 和 Bucket。
class Activity
belongs_to :project
belongs_to :trackable, polymorphic: true
end
这让我可以做@project.activities 之类的事情。为了解决隐私问题,我可以使用范围。
scope :public, -> { joins(:trackable).where(trackable: { private: false }) }
但只有 Bucket 对象以及它们的 Upload 对象和 Document 对象具有隐私标志。会员制没有。我必须为所有可跟踪模型添加隐私标志,以便它们可以与同一个界面对话。
class Membership
def private; false; end
end
class Upload
delegate :private, to: :project
end
class Document
delegate :private, to: :upload
end
然后我可以在某个策略对象中执行此操作。
@activities = if current_user.admin?
@project.activities
else
@project.activities.public
end
方法 2:在活动上添加私有标志
我可以在 Activity 上添加隐私标志。
@bucket.activities.build(project: @project) do |a|
a.private = @bucket.private?
end
然后我可以在某个策略对象中执行此操作。
@activities = if current_user.admin?
@project.activities
else
@project.activities.public
end
这很容易,但不灵活。如果我们向存储桶添加访问表,以便它们的可见性现在基于访问权限而不是用户角色,我们将不得不痛苦地重构。
有没有更好的方法来为这个 Feed 建模?你会怎么做?我不能使用任何像公共活动这样的宝石,所以请不要推荐它们。
【问题讨论】:
标签: ruby-on-rails ruby postgresql database-design data-modeling