1

The application I'm building is to allow users to download vouchers. Employers sign up for an account, add employees (who get a login), select which vouchers to enable, and then employees can see the enabled vouchers and download.

I initially created two devise models: employee and employer. This was so active record associations would be simple (employer has_many employees, employee has_many vouchers). But this would also mean separate database tables and therefore separate sign in forms.

I looked into single sign in forms for multiple users and this seemed to have the consensus that you should instead have a single User model and use CanCan and Rolify for permissions. But the problem with that is you cannot (I believe?) do active record associations between these two roles (not separate models).

I next looked at subclassing so I could do associations, but it has issues as people say Rails isn't really meant to subclass, and it seems a bit hacky.

So I'm left feeling like I have to choose the lesser of evils, whereas I really just want to find the right way.. Thanks in advance for any help.

Community
  • 1
  • 1
Scott Fister
  • 1,213
  • 12
  • 24
  • Why can't you do associations based on roles? Can't you have a text field with a role in the user model, and then create a scope, or an association via a scope? Also, in my opinion it takes less time to setup auth than to customise Devise. – Mohamad Jul 28 '13 at 15:09
  • An association to what though? Usually you'd have something like `employer has_many employees`. But in that case it's a single model - User. Could you give me an example? Mainly I need Employer has_many Employees and Employer/Employee has_many Vouchers. I don't trust myself with the encryption/security issues right now to leave Devise, just beginning with Rails. – Scott Fister Jul 28 '13 at 18:56

1 Answers1

3

So a friend of mine solved this very elegantly for me, for everyones reference:

Good question. It’s a great problem that deals with the intersection between good engineering (model implementation, database design) and user experience (single sign in form).

Assuming that Employees and Employers differ enough, it makes sense to implement them as separate models. But it also makes sense to have a single sign in form—employees and employers shouldn’t have to care that they’re signing into the right form.

Single table inheritence usually appears to be the ideal solution, but tends to best be avoided in Ruby on Rails applications unless absolutely necessary.

I’ve actually thought about this problem before, so I would suggest an implementation along these lines:

  • An Employer model.
  • An Employee model.
  • A SignIn/Login/Credentials/WhateverYouWantToCallIt model.

In terms of employer/employee associations, as before:

  • Employee belongs_to :employer
  • Employer has_many :employees

Now, considering that both models are able to sign in, it makes sense to separate these credentials into their own SignIn model. If you do some reading up on polymorphic associations (http://guides.rubyonrails.org/association_basics.html#polymorphic-associations), you’ll find that they are awesome for creating relationships where the association can be with different models.

So now you need to create associations between sign in credentials and employers and employees:

  • SignIn :belongs_to :signinable, polymorphic: true
  • Employer has_one :sign_in, as: :signinable
  • Employee has_one :sign_in, as: :signinable

The elegance of this solution (in my opinion), is that you’re able to separate your SignIn, Employer and Employee models, which not only conforms to good Ruby on Rails conventions, but is good database normalisation practice. At the same time, you have a SignIn model that makes it trivial to implement a better sign in form experience that allows both employers and employees to sign in.

Scott Fister
  • 1,213
  • 12
  • 24