How to model different users in Rails - ruby-on-rails

Question
I have a User model with authorisation and authentication logic built.
Now I realise I have three different types of users. I want to store different information about each of them.
What is the best way to handle this in Rails?
Thoughts based on current reading
I've looked at STI but from what I've read feel it is inappropriate because I'll end up with a lot of NULL fields in my database.
Ideally I'd like to not duplicate the authentication / authorisation logic for each of the three user types.
Each user will also have different functionality within the application.

You can try using polymorphic associations and creating table users with data that all types of users have and putting other data in seperate tables. Railscast epizode covering this topic.

There are lots of ways to do this. Here's one approach:
Instead of thinking of different types of users, you could think of roles that a user has.
For example, if a user could be a butcher, baker, or candlestick maker, you could have four tables: users, butchers, bakers, candlestick_makers. The latter three role tables each have a user_id column; they "belong to" the user.
If you need to enforce that a particular user has only one role, you will have to do that in the application (since this database schema would allow multiple roles for a single user).
This method is good if there is a lot of stuff that would belong in those role tables. If not, leaving some NULL columns on the users table probably won't kill you.

Related

Role based authorizations or different tables in a ruby appointment booking app

I have seen regular debates about the way to manage the different class of users.
Usually, it seems that developers prefer a role based approach (e.g. user, admin,...) with gems like Cancancan
But I'm wondering if it's applicable for an appointment booking app (appointment for doctors, teachers,... or even bookings). Indeed in this case, the 2 types of users have access to totally different pages. In its documentation about associations, Ruby on Rails guide takes the example of a medical appointment booking app with 1 table for doctors and 1 table for patients.
For this kind of app, I'm a little bit lost regarding the most efficient solution!
Thanks!
You can use a tool like Cancanan to break out the different roles and abilities, then restrict access to certain parts of the system based on those rules.
Additionally you can display only the relevant navigation or pages when the user's accessing the system so they might not even be aware of what they're not seeing.

How to set up Rails app that has different types of users?

If I want to build a Rails app that has two different types of users, let's say one type is called players and the other one is owners, what is the best and most efficient approach to modeling the app?
Things to take into account:
There should only be one Login, but different Registration forms that Owners/Players can use.
Owners can have access to a control panel but Players cannot.
Owners cannot share any of Players capabilities, but both need to be able to perform Login/Registration.
I am not using Devise, so please do not suggest it.
Different Approaches I've considered:
Using cancancan gem, but it does not really seem to meet my needs in the sense that I am not looking to create a user/admin hierarchical approach but rather a if you're a Player, then you can see these pages and perform these actions but Owners cannot and vice versa. Almost like splitting the app in two. cancancan seems that it would treat Owners as "Players with extra privileges", not different privileges entirely.
Creating separate models with separate login and registration forms, which seems like a disaster waiting to happen. One small mixup between a Players table and the Owners table, especially with the primary keys, and that will be a world of trouble where people could end up logging in to the wrong accounts.
Creating a polymorphic or has_one relation toward an Account model, which so far, seems like the best way to probably go about it. If I created a polymorphic Account model, I can store different types of Players/Owners, but how could I compare login credentials against all types?
I had been trying to find something on this matter regarding how to map this out and was surprised to not find an information on how to do this without using Devise. If anyone has any good links they can point me to that also address this matter (without Devise), please leave them in your answer! Thanks.
I'd suggest one User class with a type attribute that determines whether the user is a Player or an Owner (single table inheritance). This way you keep the registration logic in one place but can customize the forms depending on the user's class.
There must be alternatives to cancancan that help with what you want to do, or you can implement helpers yourself:
def can_access_control_panel?
current_user.is_a?(Owner)
end
You have to have a way to separate one user from another. One way is to add an attribute to the User table so you can call current_user.role and it will return "owner" or return "player".
I have used Pundit gem in the past. It lets you define which controller actions the current user is allowed to access. So as you create resources for your application, you can add a policy that specifies who is allowed to that given resource. This is the repo to the application.
This answer might help you.

Should I use Multiple user models or one big user model in Devise

I'm doing a Rails project with three user types: students, teachers, and administrators. Each user type has a dozen+ columns unique to that role. Initially I thought I'd create separate models for each type, but having a single shared login seems to pose a problem (I've found a workaround on Stack Overflow, but its complex and a few years old).
What is SOP for situations like this? Is it kosher to have a single user model with 24+ columns that will always be empty depending on the role type? Or am I better off sticking with three separate models and trying to hack a workaround to make a shared login?
Thanks!
EDIT: Oops, forgot to add the third workaround which I'm favoring: having a single user model with only columns relevant to login, and then models for each role that hold columns specific to each user type. Is that a good call?
You could make two separate models, Student and Teacher. Then add an admin:boolean field for teacher. I am assuming most admins will probably be teachers? Even if that is not the case you could just default that all admins are teachers. Three separate models is terribly bulky.

Authenticating different kinds of users in Rails

I'm making an app with 3 kinds of users: Teachers, Students and Admins.
Teachers can post Classes, with class info and assignments and stuff, and Students can enroll in those classes and do the assignments, get the materials and stuff. The Admins are just the people involved in running the site and will not be taking any of those actions, but just moderating and keeping an eye on things.
My question is, how do I built the separate authentication for those three cases? The users won't have anything in common and I'm gonna need 3 different logins/sign ups from the get-go, so it's not just a matter of assigning different roles.
How should I go about this?
All of those users have one important thing in common - they are all users. I don't see a reason for separating them. If you need users to sign up as a Teacher or Student, you can simply set up different views for those options and the default role that will be assigned to that user.
I don't see a reason why you think that it should be something different than assigning roles. If you really see many differences in data that will be stored for those different types of users, you can for example have have a common Users table and subclass them and store type-specific data in separate tables with reference to the User. However, for now I don't see anything in your description that can force something more than a simple role assigning.

rails: how to validate uniqueness of a field in two tables?

I have two tables in my app's database for two kinds of users, therapists and patients, both sign in/out with a username and password, I want to make sure that there can't be a therapist and patient with the same username, how can I do that?
also, is it possible to use the same sessions controller for both therapists and patients?
Refactor Your Design
You shouldn't have two different tables for users. You should probably have a single User table, with a field that designates the role of the User. This makes it particularly easy to select the user's role using radio buttons or a drop-down in the web application, and also allows you to enforce uniqueness on aspects of a User record.
However, why is it impossible for a patient named "John Smith" to have a therapist named "John Smith?" I'd think about that before enforcing that particular uniqueness constraint.
Finally, a session is generally shared across controllers, and a controller can certainly read from more than one model at a time. In your case, refactoring to a common User model will reduce the need to do something complex in this regard.

Resources