使用 CanCan 嵌套子元素
Nested Child Elements with CanCan
Ruby 新手,正在处理内部应用程序的更改。
我正在使用 CanCan,以便我们可以限制对页面的访问。
我有以下有效的代码,但我知道有更好的方法可以为未知数量的子元素编写代码。
一个用户有一个直线经理,谁有一个直线经理...e.t.c。我正在尝试实现树状层次结构,以便高层管理人员可以查看他们的员工帐户,但前提是他们是该员工层次结构的一部分。在下面的示例中,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}}}}}
感谢任何帮助,因为这不是一个长期的解决方案,因为嵌套的数量可能会增加,并且需要对不仅仅是用户进行处理。
一个高效的解决方案是从数组中的数据库中收集所有 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
您可以使用 closure_tree gem,这将允许您管理模型中的层次结构。然后,您可以像这样在模型中添加一个实例方法:
def managed_by? user_id
self_and_ancestors_ids.include? user_id
end
然后你可以像这样将障碍传递给你的康康舞能力
can :read, User, User.all do |fetched_user|
fetched_user.managed_by? user.id
end
Ruby 新手,正在处理内部应用程序的更改。
我正在使用 CanCan,以便我们可以限制对页面的访问。
我有以下有效的代码,但我知道有更好的方法可以为未知数量的子元素编写代码。
一个用户有一个直线经理,谁有一个直线经理...e.t.c。我正在尝试实现树状层次结构,以便高层管理人员可以查看他们的员工帐户,但前提是他们是该员工层次结构的一部分。在下面的示例中,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}}}}}
感谢任何帮助,因为这不是一个长期的解决方案,因为嵌套的数量可能会增加,并且需要对不仅仅是用户进行处理。
一个高效的解决方案是从数组中的数据库中收集所有 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
您可以使用 closure_tree gem,这将允许您管理模型中的层次结构。然后,您可以像这样在模型中添加一个实例方法:
def managed_by? user_id
self_and_ancestors_ids.include? user_id
end
然后你可以像这样将障碍传递给你的康康舞能力
can :read, User, User.all do |fetched_user|
fetched_user.managed_by? user.id
end