【问题标题】:Nested Child Elements with CanCan使用 CanCan 嵌套子元素
【发布时间】:2017-03-24 10:44:24
【问题描述】:

Ruby 新手,正在为内部应用程序进行更改。

我正在使用 CanCan,以便我们可以限制对页面的访问。

我有以下有效的代码,但我知道有一种更好的方法可以为未知数量的子元素编写代码。

一个用户有一个直属经理,他有一个直属经理……等等。我正在尝试实现树形层次结构,以便顶级经理可以查看他们的员工帐户,但前提是他们是该员工层次结构的一部分。在下面的示例中,John 应该能够查看 Jane 和 Jack 的个人资料,但不能查看 Josh 或 James 的个人资料。

  +-------------+----------------------+--------+
  | user_id     | name                 | parent |
  +-------------+----------------------+--------+
  |           1 | JOHN SMITH           |   NULL |
  |           2 | JANE SMITH           |      1 |
  |           3 | JACK SMITH           |      2 |
  |           4 | JOSH SMITH           |      5 |
  |           5 | JAMES SMITH          |   NULL |
  +-------------+----------------------+--------+

Ability.rb 的一部分

class Ability
    include CanCan::Ability
    def initialize(user)
      user ||= User.new
      can :read, User, id: user.id
      can :read, User, line_manager: user
      can :read, User, line_manager: {line_manager: user}
      can :read, User, line_manager: {line_manager: {line_manager: user}}
      can :read, User, line_manager: {line_manager: {line_manager: {line_manager: user}}}
      can :read, User, line_manager: {line_manager: {line_manager: {line_manager: {line_manager: user}}}}
      can :read, User, line_manager: {line_manager: {line_manager: {line_manager: {line_manager: {line_manager: user}}}}}

感谢任何帮助,因为这不是一个长期的解决方案,因为巢的数量可能会扩大,并且需要在不仅仅是用户身上完成。

【问题讨论】:

  • 您能发布您的用户和直线经理类定义吗?

标签: ruby-on-rails ruby nested cancan


【解决方案1】:

一个高效的解决方案是将数据库中的所有 id 收集到一个数组中,并让用户访问它们。没有 DB-Queries 的更脏的解决方案是这样的:

can :read, User.all do |r_user|
  until r_user.line_manager.nil? do |manager|
    return true if manager == user
    r_user = manager
  end
  return false
end

(请注意,代码未经测试,但这样的东西应该可以工作)。 但这会一次又一次地循环所有用户。我建议通过查询收集 id

【讨论】:

  • 谢谢医生。我最终收集了您在数组中提到的 ID 并进行了迭代。
  • 感谢您的接受。而且我真的不喜欢危及我的观点,但我的回答在收集id方面并没有多大作用。因此,我建议您使用当前的解决方案更新您的问题,也许我们可以帮助您进一步改进它。如果它已经是一个很好的解决方案,我会很高兴我帮助了你;-)
【解决方案2】:

您可以使用closure_tree gem,它允许您管理模型中的层次结构。然后,您可以像这样在模型中添加一个实例方法:

def managed_by? user_id
  self_and_ancestors_ids.include? user_id
end

然后你可以像这样将一个块传递给你的 cancan 能力

can :read, User, User.all do |fetched_user|
  fetched_user.managed_by? user.id
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 2023-02-21
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多