我想对我正在尝试建模的活动Feed提出第二意见。我想出了三种方法。
我有一个Project,Membership,Bucket,Upload和Document模型,都是ActiveRecord模型。一个项目有很多成员和许多桶。存储桶有很多上传,上传有很多文档。我想跟踪会员资格,存储桶,上传和文档(更新,删除,创作等)的活动。
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
这本身相当容易。但是一些存储桶是私有的,只有管理员才能看到。这意味着他们的活动,上传活动及其文档只有管理员才能看到。
活动属于可跟踪对象,在本例中为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
我可以在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?你会怎么做?我不能使用像公共活动那样的宝石,所以请不要建议它们。
答案 0 :(得分:1)
我认为你的第一种方法要好得多,我唯一能做得更好的是:
class Activity
scope :auth_with, -> (auth) { joins(:trackable).where(trackable: { private: trackable_access(auth) }) }
class << self
private
def trackable_access(auth)
return false unless auth
auth.admin?
end
end
end
然后你可以打个漂亮的
@project.activities.auth_with(current_user)
并且不关心访问问题,您的访问逻辑也只在一个地方,而且它唯一关注的地方 - Activity
,因此更改访问逻辑将归结为替换auth.admin?
in trackable_access
与任何其他类型的身份验证。
顶部的樱桃使trackable_access
变为私有,因此您无法在不遗漏的情况下致电Activity.trackable_access(...)
。
这当然只是我对此事的看法,但我希望我能以某种方式帮助:)
答案 1 :(得分:0)
我会诚实地将两种方法结合起来。第二种方法可以实现您真正希望数据反映的内容 - 此活动是否为私有?
我可能会在:private
钩子中设置Activity
上的before_save
字段,其逻辑类似于“如果我属于私有{{ 1}}”。
我更喜欢这种方法,因为如果您的逻辑使Bucket
私有变更,或者您需要为其他类型的访问添加标记(例如Activity
),您可以添加类似的挂钩并运行脚本以更新所有过去的viewable_to_managers
个对象。