Givey is known for its employee matching engine. If you are registered as a business employee on Givey and the business has set up matching, you will be matched to a certain percentage for each donation.
The way this worked is we had a pivot table in the database which housed all of the employees. Each employee record was given a user id, a business id and 2 boolean flags to show if the employment was confirmed and wether they were an admin of the business or now. Each employee of a business could access the business’ settings regardless of their admin status, which wasn’t ideal.
We also had admins for charities. Each charity had one admin user which was stored on the charity table in our database as a simple ID which related to the user ID. However, we had a lot of requests for charities to have multiple admins.
So I got to planning the feature. My first thought was to follow the way we do employments for businesses. Create a new pivot table for charity admins. A simple enough task, not much would need changing. But then I got ambitious.
We currently use a Ruby gem ACL9 which we use as access control for the main Givey admin panel. This gem makes it simple to give certain users admin rights, but also assign them to groups and restrict certain controllers or methods to said groups. So I thought about incorporating the gem into the charity admin section.
Then I got more ambitious. I thought, why not include this role based system for business employments too?
After a bit of thought I decided that the ACL9 gem wasn’t the way forward. It added a lot of extra bloat to the code and to the database which wasn’t needed. If we had 2 pivot tables (one for business employees and one for charity admins) then we would need another 2 pivot tables for the roles associated with them. That meant 5 table joins just to figure out if a user had a role within a business or charity (users joins businesses joins employments joins roles joins roles_employments).
So, I thought to myself, why should charity admins be in a separate pivot table? It would share exactly the same information as the business employees pivot table afterall. So the final decision was to use the same employments table for charities and businesses.
The employments table has a business_id column (integer) and an admin column (boolean), so there was a bit of work needed to make this happen. I added two extra columns, one which was a polymorphic relation to either a business or charity, and one which detailed the role as a simple string.
So in the case of a business, the role can either be owner, admin or member. Charities only have owner and admin.
I was quite pleased with this setup. I didn’t add any more tables, in fact, I removed some as I decided to completely remove the ACL9 gem. The problem was with the table name. Charities don’t really have “employments” per se. I have a plan for this but that is for another blog post. For the front end code, we simply refer to these employments as admins if the polymorphic relation happens to be a charity.
Now came the stressful part. Having pushed the changes to the branch, our CI reported 407 failures in the code base. The old admin user field for charities and businesses is used everywhere on Givey so it all had to be changed. The old admin_user for charities is now the owner. So I had to change all references to that in the code base. I also had to create a simple rake task to look at all of the charities and create an owner employment for it which was referenced by the admin_user. Another rake task was also created for the business employment updates in order to create the new employments with the correct role.
Now when you add employments to your business or charity on Givey, you can specify a role. So a charity and business has one owner and can have many admins. A business can also have many members.
The last step was to restrict certain settings for the business/charity. It’s nice to have the new intern be matched on Givey, not so nice for them to have access to your billing information. So we simply restricted certain sections based on role. Owners can access everything and admins can not access sections like document uploads or billing information. In the case of business members, they cannot access the settings pages.