RoR modelling for different users, Devise, Active Admin - ruby-on-rails

I have a single users table through Devise. Branching off this table are 3 other models (author.rb, seller.rb and buyer.rb) with each having a one to one relationship with the main Users table.
The reason for this is each have some unique attributes and I want to keep the main Users table tidy. I am using active admin and want to avoid redundant fields when registering a new user.
Currently I am using enums to assign user roles:
enum role: [:author, :sellers, :buyers]
The problem is when I set a role it works in the sense that I can restrict what a user sees based on that role however there is a big issue I have below.
The problem:
I want to be able to register an Author. Everything good so far. But I also want to be able to register a Buyer and then associate that buyer with the author as two different users. At the moment a user is becoming both at the same time through nested forms in active admin I used which is not what I want. I want a user to be a buyer and the other user to be an author.
Maybe I don't have my relationships set up correctly for this? Or it could be a problem in active admin?
class Author < ActiveRecord::Base
belongs_to :user
end
class Buyer < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :author
has_one :buyer
end
Basically I want to be able to register two different users and after that associate them and I don't know how to do this. Any advice much appreciated.

Related

Devise and multiple users models

I'm fairly new to Rails and trying to setup an app that uses several types of users: Teacher, Student, Admin (and likely more to come).
The reason I want different models is because the attributes for the various users differ. For example, Teacher have topics taught, a profession, and a diploma. Whereas Student and Admin do not. Students can leave reviews of teachers, etc.
I thought of having a general User model for the general information such as name, email, and other contact information and each type of user would inherit of it:
class Admin < User
end
class Teacher < User
end
class Student < User
end
And so on.
I'm using Devise for authentication and used STI for differentiating between user roles through a role field in the table.
The thing is, where and how can I tell my app to generate a current_user of the right class when the user logs in? And where should I store the additional info on each model (ex the profession of a teacher). In the users table?
About the relationship with their objects, for example, a teacher has many topics he teaches. How can I make sure only teachers have topics and not students?
I've looked into CanCan but was utterly confused.
My advice is : DONT DO THAT ! You are mixing very different concerns and will end up with the infamous God Object.
User is here only for authentication, you should not mix it with your domain models. Teacher / Student / Admin etc should be separate models from User. You can eventually create a People table and have Teacher Student and Admin inherit from it.
class Student < Person
Or have a different table for each of them so there's no possible confusion (also someone might be both a Teacher and an Admin for example, separating stuff keeps your options open)
But whatever you choose keep User out of it !
If you want to tie a User to Teacher / Student / Admin use associations and give each of them a user_id.
class Student < ActiveRecord::Base
belongs_to :user
end
Please have a look into this link. Hope this may helpful to you:-
http://funonrails.com/2011/12/multiple-resources-registrations-with/
Also, you can manage relationship with their objects by making model(table) as polymorphic like:-
# Topic Model:
belongs_to :readable, :polymorphic => true
Also in topic model there are two more fields:-
readable_id and readable_type.
# Teacher Model:
has_many :topics, as: :readable
# Sturdent Model:
has_many :topics, as: :readable

User owns a model and other users can join this model

I want to creat an application where a User can create a Room and is the only owner of it. Other users should be able to join a Room, just one at the time and only they should be able to see what is happening in this Room.
So i created a controller rooms_controller and the model Room.
Btw I'm using devise to handle all the Userstuff.
So what should i put into the user.rb file? has_one :room? belongs_to :rooms?
How can users join a model?
Does a User have an one.to-one relationship with Room? In that case User has_one Room. Or can a User create many Rooms? A User can join a Room, if, for example, there is a Rooms_Visitors table where the RoomId and the UserId identify a row.
Its hard to answer without knowing your broad use case.
I advice that you study a bit on SQL relations, then the answer for your use case will become clear to you.
You can design the models this way. You can actually have two types of users: Owner and User and they can inherit from the BaseUser where BaseUser being the class with all the common user attributes.
And, your model associations can look like this:
class BaseUser < ActiveRecord::Base
# all the common user attributes here
end
class Owner < User
has_one :room
end
class User < BaseUser
has_many :rooms
end
class Room < ActiveRecord::Base
belongs_to :owner
belongs_to :user
end
owner has one room and room belongs to owner.
user has many rooms and room belongs to user.
You have to add owner_id and user_id in your rooms table.
You can also have a user_type column in your base_users table to indicate what type of user is this (i.e. owner or user).
Also, take a look at the cancancan gem which is an authorization Gem for Ruby on Rails application. You will need to have different types of abilities for example: owner will be able to create the room but user can't create the room, they can only join. You need to handle these things using authorization.

Modeling Users in Rails

I need advice/help in implementing the design of my models in a university HR web application that I'm currently developing.
First, I have these models for my tables with their fields:
Students
* different fields
Faculty
* different fields
Users
* username
* password_digest
I have Students and Faculty objects for CRUD that have their unique fields/attributes in their own tables. At the same time, I see these objects as the types of Users that uses the app.
I'm confused on how to model them properly, experimenting either with ActiveRecord's STI or Polymorphism techniques. All I want the app to do is to recognize the type of User that is signing in and then display or redirect to the appropriate page for that type of User. At the same time have reference to its associated record in the Faculty or Student table.
What is best way to approach this assuming I have these conditions:
Users can either be a Student, Faculty, or Admin. Later on I can add/model non-faculty members to the applicaton as well.
Student/Faculty can opt to have or not have an associated User account. (Some students and faculty members don't want to use the app)
Admin users have access to the administrative (CRUD) side of the app. Student and Faculty can only handle their own records.
I might be wrong, but my bet is to go polymorphic and put the reference in the User model:
class User < ActiveRecord::Base
belongs_to :userable, polymorphic: true
end
class Student < ActiveRecord::Base
has_one :user, as: :userable
end
class Faculty < ActiveRecord::Base
has_one :user, as: :userable
end
P.S.: I don't know if the "userable" term sounds right, just correct me if there's a better way to name it.
One Simple method is, So you can easily manage with common fields as well
# User should have a type field (string)
class User < ActiveRecord::Base
end
class Student < User
end
class Faculty < User
end
This spells out very clearly the way you need to go:
"Student/Faculty can opt to have or not have an associated User account. (Some students and faculty members don't want to use the app)"
This means that Student, Faculty and User need to be completely different things: you need to be able to have a Faculty account which doesn't have a user account. So, your polymorphic approach is the right way to go i think.
BTW, i would rename Faculty, since Faculty has a different meaning: a faculty is a department or division within the university, it's not a person. Later on in your app's development you may need to associate classes, students or staff members with a Faculty and then it's going to get confusing. I would use FacultyMember since that's how staff are usually described.
"userable" is an awkward word to use for the relationship. What about "scholar"? That can describe both staff and students, and it conveys the idea that it's referring to an actual person, as opposed to "user" which is really a user account rather than a person.

Confused about Ruby on Rails Active Record structure

I'm having trouble coming up with a way to structure my models to the the following:
I have Users through Devise - Users can have a role of (amongst others) Sales, Admin and Client. This is set through a HABTM with the Role model. I've set up a method so I can do the following
user.is? :Client
What I need is the following:
Users that have the Role of Sales can have any amount of clients.
So when a SalesPerson logs on, I can do User.clients to fetch all clients related to them.
Users that have the Role of Client can only have one client.
When a new Client signs up online, I want to create their user trough devise, and then also create a client through nested values, linked to the user they created.
Clients should have one SalesAgent, using the User model
When viewing the client, one should be able to have a dropdown to select the SalesAgent from. This should, as above, use the User model.
Clients should have only one Devise User with the role of Client, using the User class
Clients should be able to log on through devise to access their details, track orders, etc.
As you can see, this is incredibly confusing, and I'm not sure what the best way would be to pull this off. The only thing I can think of would be to use a HABTM between Users and Clients, and then Joins and hacks in the forms to make it work. Is there a better way to do this? I've looked at perhaps using
has_one :sales_agent, :class_name => "User"
But can't get it working. :/
Rather than overloading the User class with a roll-your-own single table inheritance scheme, it's often better to break out the roles in the db. It sure makes things clearer at this stage, and it's a better way to store data specific to clients or sales agents that don't belong to any user. E.g.:
class User < ActiveRecord::Base
has_many :clients
has_many :sales_agents
end
class Client < ActiveRecord::Base
belongs_to :user
belongs_to :sales_agent
end
class SalesAgent < ActiveRecord::Base
belongs_to :user
has_many :clients
end

Rails Devise User both belongs_to and has_many

After spending a few days of trying to find an answer online, I figured I should ask for help. I'm trying to figure out the best way to implement these relationships using Rails Associations.
I have 4 models: User, Transfer, Building and Bag.
A User has a role attribute. The possible values for role are 'admin', 'building_contact' and 'guest'.
This is what it looks like in a tree structure. The Admin, Guest and BuildingContact is the role of a #user:
Admin
|
Transfer
/ \
Guest Building
| |
Bag BuildingContact
Therefore:
Admin has_many :transfers
Transfer belongs_to :admin
Transfer has_many :guests
Guest belongs_to :transfer
Guest has_many :bags
Transfer belongs_to :building
Building has_many :transfers
Building has_many :building_contacts
What is the best way to implement the relationship with the User model?
Thanks in advance!
One of the fundamental questions that I'd as is:
Will a user have more than one role? I'm guessing not, since you have a single role attribute. They may share many things, but I'd say that the business logic for the different user types would create different models. How about ditching that role attribute and instead using a type attribute and using STI?
class Admin < User; end
class Guest < User; end
class BuildingContact < User; end
That way you will have the inherited User capabilities but you can define differing business logic where appropriate. You can extend this into different controllers and views, otherwise I would think you would risk having a much bigger User class than you would want to.

Resources