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}}}}}
我感谢任何帮助,因为这不是一个长期的解决方案,因为巢的数量可以扩大,而且需要的不仅仅是用户。
答案 0 :(得分:0)
一个高性能的解决方案是从数组中收集数据库中的所有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
答案 1 :(得分:0)
您可以使用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