I setup roles for the User model, for now, I just have a role string column for the users table. The value could be admin, salesperson, instructor or student.
Now I have a ScheduledSession model that an Instructor is supposed to teach. I have an instructor_id column, which is supposed to have an id from the users table (an user with a role of instructor).
So how can I setup the association in the models? in the User model is doesn't seem right to add has_many :scheduled_sessions because if the role is a salesperson or an admin, it just doesn't feel right. or setup something like belongs_to :user, :as instructor in the ScheduledSession model, but I get error Unknown key :as.
How would you set this up?
You want to set up your belongs_to slightly differently in the ScheduledSession model.
belongs_to :instructor, :class_name => 'User, :foreign_key => 'user_id'
This allows you to refer to the instructor of a ScheduledSession object and have it point to an entity in the User table.
There's no way around having a has_many relationship on your User model if you want to pursue a role based User with each user having a single role. Without it, you'll have no mechanism to retrieve the scheduled_sessions associated with a user.
An alternative might be to use Single Table inheritance here, which would allow you to create Admin users who don't have SchededSessions, but Instructors who do. You'll still store all of these in the same table, but ActiveRecord will make it easier for you to compartmentalize them.
Related
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.
I have such models Supplier and Role.
Supplier should have one role, one role might belongs to multiple suppliers,
so I don't want to add foreign key to the Role model
I wan't to create all roles at the beginning and then add role to a supplier whenever I want
Is there a way to do that??
The foreign key in this case needs to go in Supplier. You can't put it in Role, if a Role can belong to many suppliers.
That makes this a belongs_to relationship by Rails convention, not a has_one.
Your Supplier needs a column called role_id and an association belongs_to :role. Your Role can then have a has_many :suppliers, if you want to be able to find all suppliers who use a given role.
I'm using Ruby on Rails 3.2.8 with Sorcery authentication.
What is the best way to create sub-users accounts?
Ideally, I would like to invite members by email and have them click on a link and they choose their username/password. Is it possible to do this within the same user table so they all can login from the same login page?
To wrap your head around what I'm trying to do is... Employer can add/invite employees to join the system and any data input to the system will belong to the employer.
Personally I would handle this as a single table inheritance model with a same-table association column.
Put a field called boss_id on your users table. You'll have the main User model, that has the Sorcery authentication stuff and any common logic. Underneath it you have Employer and Employee. They have a method called boss: for the employer, this returns self or nil (whichever you find makes most sense), whereas for employees, this is an actual association method, something like this:
class Employee < User
belongs_to :boss, class_name: 'User'
end
When an employer sends out an invitation, direct the invitees to a URL for invitations specific to the employer, like:
http://yoursite.com/employer/3/invitation
When the user creates their account you associate them to their owning employer.
When an employer views their data, ensure that you pull their child employees' data as well, using the users table as a join table:
class Employer < User
has_many :employees, class_name: 'User', foreign_key: 'boss_id'
has_many :contacts # Or whatever your application-specific stuff is
# that you want employers to see through their employees
has_many :employee_contacts, through: :employees, source: :contacts
end
If you need to assign ownership to employers in the database, I'd use an observer to watch for saves on the owned models, and if they are saved by someone with a boss, set an additional column to that boss' ID.
I have a model called company and one called user, and User belongs to Company and Company has many Users.
But I want to store on the company model the master company admin user, but I want to do it with a custom name.
So, i want to do this: comapany.owner.name .
How can I do this in Rails 3?
your Company needs one additional field
owner_id :integer
then add to Company
belongs_to :owner, :class_name => "User"
I have a user table, and have a role column, that identify their role. Now, I want to add a "Student" table, that have the student's student number, and I also want to add a "Teacher", to store the teacher's salary.
Both the Student and Teacher are the subclass of User. Now, I added a role column already in the User table, "T" = Teacher, and "S" = Student. Now, I want to add "Student" and "Teacher" in the database. What should I do? Generate scaffold or migration only? Also, it is necessary to modify my models? or I just need to modify the controller only??
Thank you.
This sounds more like a job for Rails' single table inheritance. It's really easy to use. Instead of using a separate table to store roles. Inherit your student and teacher models from User.
for example:
User < ActiveRecord::Base; ... end
Student < User; ... end
Teacher < User; ... end
Rails automatically creates a type column and stores the class there.
User.all will return all users Student.all will return users where the type is matches Student and Teacher.all will do the same for all teachers.
You can read more about single table inheritance at the ActiveRecord documentation, and here.
As nuclearsandwich said, this is a situation that calls for rails STI (single table inheritance), not polymorphic associations.
Just to highlight the difference:
1) Singe table inheritance is used when you have different models that are very similar to each other with minor differences. STI lumps all models in the same database table, with fields (columns) for all the models that use this table. There is also a "type" field which indicates which model this record belongs to.
Your case is a perfect example of STI. You have user, student, and teacher models, they share a lot of common fields and functionality, you just want an extra field for the student and the teacher.
2) Polymorphic association is used when you have a model that will be associated with different models. For example, imagine you have an "Address" model. Also you have a "Company" and a "User" model, both of which can have an address.
In your Address model, you can specify
belongs_to :user
belongs_to :company
And then make sure if the address belongs to a company not to call address.user and vice-versa. However, a better way to do it would be through a polymorphic association. In your address model you do
belongs_to :addressable, :polymorphic => true
and in your user and company model you add
has_one :address, :as => :addressable
This allows the address model to polymorph (literally: transform into many) its association, and be connected with multiple different models through a single association.