嵌套的子元素与CanCan

时间:2017-03-24 10:44:24

标签: ruby-on-rails ruby nested 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}}}}}

我感谢任何帮助,因为这不是一个长期的解决方案,因为巢的数量可以扩大,而且需要的不仅仅是用户。

2 个答案:

答案 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