对活动Feed进行建模

时间:2015-07-01 14:29:30

标签: ruby-on-rails ruby postgresql database-design data-modeling

我想对我正在尝试建模的活动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

这本身相当容易。但是一些存储桶是私有的,只有管理员才能看到。这意味着他们的活动,上传活动及其文档只有管理员才能看到。

方法1:多态活动类

活动属于可跟踪对象,在本例中为MembershipDocumentUploadBucket

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?你会怎么做?我不能使用像公共活动那样的宝石,所以请不要建议它们。

2 个答案:

答案 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个对象。