Skip to content

Gem to ease your pain when workign with user hierarchies

License

Notifications You must be signed in to change notification settings

Tereci/user_hierarchies

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

user_hierarchies

This gem should serve as a convenient way, how to work with user hierarchies. This was specifically tailored for the model used in Salesforce because we work a lot with it. If you are not familiar with it the user is stored in Salesforce db like this

Name, ID, ManagerID
Joe, 1, 2
Bob, 2, 3
Jim, 3,

This is called adjacency list. This gem wraps these lines in a model and enables to express the relationships in reasonable methods so even a mediocre guy should be able to get something out of it if he knows enough ruby. The problem with adjacency lists are that they are quite useful for programming languages but rather unpleasant to use in SQL like languages. To see this in action.

In SOQL you can very effectively write something like

SELECT Name, Manager.Name where ID = 1

But it is very tricky to get list of all managers/subordinates of Joe or to determine if Jim and Bob are on the same level in the hierarchy. Generally without recursion you cannot achieve easily similar results in SQL. The same problem is much easier in a general programming language like Ruby. And with nice API it can be even easy to read.

# INTEGRATION WITH SALESFORCE WILL BE IMPLEMENTED SOOOOOOOON
require 'user_hierarchies'

GoodData::UserHierarchies::UserHierarchy.from_sf(login, password) do |hierarchy|
    hierarchy.users.each do |user|
        puts "#{user.name} => #{user.all_subordinates.map {|s| s.name}.join(", ")}" if user.is_manager?
    end
end

This script will download the hierarchy from SF account with credentials you provide and prints all subordinates of a person if that person has any. You can do the same for a file

::UserHierarchies::UserHierarchy::read_from_csv("file_name") do |hierarchy|
    hierarchy.users.each do |user|
        puts "#{user.name} => #{user.all_subordinates.map {|s| s.name}.join(", ")}" if user.is_manager?
    end
end

Since I was trying no to tie the implementation to expectations about specific file format you sometimes need to provide the program with some additional hints where to look for things. For building the hierarchy you need to tell the program where to find user id and where to find manager’s id. It is also useful to put there a field that is used with to_s method for descriptions etc.

Imagine this CSV

name,UsErID,MaNaGeRID
Joe, 1, 2
Bob, 2, 3
Jim, 3,

This program does exactly the same thing as the one above

GoodData::UserHierarchies::UserHierarchy.read_from_csv("file_name", {
    :user_id => "UsErID",
    :manager_id => "MaNaGeRID",
    :description_field => "name"
}) do |hierarchy|
    hierarchy.users.each do |user|
        puts "#{user.name} => #{user.all_subordinates.map {|s| s.name}.join(", ")}" if user.is_manager?
    end
end

Besides that there is little metaprogramming magic built in so if you have for example some additional information that you would like to use say

name,user_id,manager_id, some_arbitrary_info
Joe, 1, 2,Foo
Bob, 2, 3,Bar
Jim, 3,,Baz
  • Arbitrary fields

It is very easy to use this information in your program

GoodData::UserHierarchies::UserHierarchy.read_from_csv("file_name") do |hierarchy|
    hierarchy.users.each do |user|
        puts "#{user.name} => #{user.some_arbitrary_info}"
    end
end

As you can see the method name is based on the header of csv

  • Interactive Usage

Sometimes it is nice to just dive inside the hierarchy and literally walk inside it. You can easily do this with this gem

GoodData::UserHierarchies::UserHierarchy.from_sf(login, password) do |hierarchy|
    hierarchy.go_interactive
end

when you run this script you will be able to use REPL with all the stuff preloaded. You can then interactively play with the hierarchy

joe = find_user("1231safdas432")
bob = find_user("123123wqe2423")

joe.is_manager?
bob.is_manager?

bob.is_manager_of? joe
bob.is_subordinate_of? joe

bob.all_subordinates.size

bob.has_manager?
bobs_manager = bob.manager

bobs_subordinate = bob.subordinates.first

Speed

I do not know if the library is fast or not. For the biggest customer I have used this which has like 6000 users this was fast enough (under 1 second to generate what I needed. I bet there might be done some improvements. If you have some suggestions let me know.

Contributing to user_hierarchies

  • Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet

  • Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it

  • Fork the project

  • Start a feature/bugfix branch

  • Commit and push until you are happy with your contribution

  • Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright © 2011 Tomas Svarovsky. See LICENSE.txt for further details.

About

Gem to ease your pain when workign with user hierarchies

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Ruby 100.0%