new to Ruby and working on changes for an in-house application.
I am using CanCan so that we can restrict access to pages.
I have the following code which works but I know that there's a better way that this can be written for an unknown amount of child elements.
A user has a line manager, who has a line manager... e.t.c. I am trying to achieve a tree hierarchy so that top line managers can view their staffs account, but only if they are part of the hierarchy of that staff. In the below example, John should be able to view Jane and Jack's profile, but not Josh or 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 |
+-------------+----------------------+--------+
Part of 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}}}}}
I appreciate any assistance as this isn't a long term solution as the amount of nests can expand and requires to be done on more than just the user.
A performant solution would be to collect all the ids from the db in an array, and give the user access to them. A dirtier Solution without DB-Queries would be something like:
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
(Note the code is untested, but something like this should work). But this would loop all the Users again and again. I would suggest to collect the id's with a query