在一个Rails 5应用程序中,我有一个shortlist
模型和一个user
模型在HABTM关系中,用户由设计控制。这一切都像预期的那样工作,每个用户都可以看到他们自己的候选名单(仅限)。
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 << User.second
),但这会给他们完全的读写权限。
cancancan gem看起来很有前途,但我不确定如何配置功能,以允许User1完全控制他们的候选列表,并赋予User2只读访问User1与他们共享的候选列表。
如何限制第二个用户具有只读访问权限?
您在shortlists表中添加owner_id
列的解决方案实际上是一个很好的解决方案,因为它可以让您有效地快速加载关联,并且处理起来不那么麻烦。
如果您想通过连接表跟踪创建记录的用户,那么通过角色系统是可能的,但它会更加笨拙。Rolify宝石就是一个通用角色系统的例子。
你应该做的一件事是使用has_many through:
代替几乎无用的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中都是不可能的。
作为解决方法,我在候选名单上添加了owner
标志,在创建候选名单时计算为current_user.id
。这使我能够区分所有者和查看者。
在保存候选列表之前,我检查@shortlist.owner == current_user.id
是否存在,如果没有,则显示错误信息。
这个方法效果很好,但是我很想知道是否有一种不那么粗糙的方法。