【问题标题】:How to share a Rails model with other Devise users in read-only mode?如何以只读模式与其他 Devise 用户共享 Rails 模型?
【发布时间】:2021-09-09 03:40:02
【问题描述】:

在 Rails 5 应用程序中,我有一个 shortlist 模型与 user 模型的 HABTM 关系,用户由 Devise 控制。这一切都按预期工作,每个用户都可以看到自己的候选名单(仅)。

class Shortlist < ApplicationRecord
  has_and_belongs_to_many :users
 ...

class User < ApplicationRecord
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable
  has_and_belongs_to_many :shortlists
  ...

class ShortlistsController < ApplicationController
  def index
    @shortlists = current_user.shortlists
    ...

现在我希望允许用户与其他用户“共享”候选名单,这些用户将对共享的候选名单拥有只读访问权限。

我可以将第二个用户添加到候选名单 (@shortlist.users &lt;&lt; User.second),但这会给他们完全的读写权限。

cancancan gem 看起来很有希望,但我不确定如何配置这些功能,以允许 User1 完全控制他们的候选名单,以及授予 User2 对 User1 与他们共享的候选名单的只读访问权限。

如何将第二个用户限制为只读访问权限?

【问题讨论】:

  • CanCanCan 看起来很有希望,直到你不得不做一些稍微复杂的事情并且它愚蠢的 DSL 阻碍了你。几年前,我将所有应用程序都更改为 Pundit。一开始有点难以理解,但它只是普通的旧 OOP 并且可以更好地处理复杂性。

标签: ruby-on-rails devise relationship has-and-belongs-to-many cancancan


【解决方案1】:

您在候选名单表中添加owner_id 列的解决方案实际上是一个很好的解决方案,因为它可以让您有效地预先加载关联并且处理起来不那么麻烦。

如果您想通过连接表来跟踪创建记录的用户,这可能通过角色系统进行,但它会更笨重。 Rolify gem 就是一个通用角色系统的例子。

您应该做的一件事是使用has_many through: 而不是the near useless has_and_belongs_to_many

class Shortlist < ApplicationRecord
  belongs_to :owner, 
    class_name: 'User'
  has_many :shares
end

# rails g model user:belongs_to shortlist:belongs_to
class Share < ApplicationRecord
  belongs_to :user
  belongs_to :shortlist
end

class User < ApplicationRecord
  has_many :shortlists, 
    foreign_key: :owner_id
  has_many :shares
  has_many :lists_shared_with_me,
    through: :shares,
    source: :shortlists 
end

这使您可以向表格中添加其他列,例如允许您授予其他用户编辑候选清单或自动到期日期的权限的标志。您还可以为每个共享生成唯一的 URL,以跟踪正在使用的“共享”。 HABTM 不可能做到这些。

【讨论】:

  • 非常感谢马克斯。实际上,我确实切换到了 has_many through: 关联,但我在回答中省略了这一点,因为它并没有真正影响结果。
  • 问题的其余部分会有点太长,无法回答。理想情况下,您应该使用 Pundit 或 CanCanCan 等授权库。如果不是,您应该使用raise AuthorizationError unless @shortlist.owner == current_user 之类的东西来摆脱您的方法。然后,您使用 rescue from 来处理异常。您想使用异常来解决问题的原因是立即停止执行并中断添加到控​​制器的任何可能产生副作用的回调链。
  • 酷,我会调查的。再次感谢!
【解决方案2】:

作为一种解决方法,我在候选名单上添加了一个owner 标志,在创建候选名单时计算为current_user.id。这让我可以区分所有者和查看者。

在保存入围名单之前,我会检查是否有@shortlist.owner == current_user.id,如果不是则显示错误消息。

这很好用,但我很想知道是否有一种方法不那么 hacky。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多