Good Afternoon All,
I'm just trying to think the best way to set this up at the beginning rather than changing everything at the end.
I have 3 models. I have a devise generated model called User.rb a model called employer.rb and candidate.rb.
My understanding is that once the user signs up and selects a role I can assign a role type after sign up and redirect them to a page on role where they can fill in the fields.
Each model has different fields and different data requirements.
How would I go about this, any pointers or ideas of how I'd approach this...
This seems like a job for STI (single table inheritance)! Add a type column to your User model, and have the Employer and Candidate models inherit from User. There are a lot of STI with rails references out on the internet, but here's one specific blog post.
Related
I've created 2 tables, one for users and one for admins.
I created 2 tables as they both collect different information, but I want to be able to allow a sign in using an email address and password from both the admin and user tables via the same form.
Is this possible? I've looked around and people seem to have created 1 users table and added an admin boolean, but I wanted to avoid this and I didn't want to collect unnecessary data if I didn't need to.
Any help and assistance about how to best go around this would be great.
If you are implementing something from scratch, then it is simply a matter of coding it. I think this approach has some inherent flaws and I would avoid it.
If you want to have some segregation on the model side of things, I suggest you use STI. That way there is some shared behaviour/attributes and the distinctions can be coded separately, so you have your protection.
If you have plenty of distinct attributes, I would suggest separating them from your user/admin and creating an "admin_profile" model that belongs_to :admin and a "user_profile" that belongs_to :user.
And to make coding "transparent", you can create accessors in your admin model class to get/set the profile attributes seamlessly. Say you have an is_cool attribute on the admin_profile model, but you'd like to access it as
imadmin.is_cool
You can have in your admin.rb model
has_one :admin_profile
def is_cool
self.admin_profile.is_cool
end
be careful cause the has_one relationship may return nil if there is no profile associated with the admin/user.
I have a problem, i need create 3 type of users with devise. these users have different fields. I thought about creating a table but would have many blank fields.
any recommendations? I'm very confused. I need a tutorial :)
Thanks friends.
You are looking for something called Single Table Inheritance. Basically you create one user model with devise which has a column "type" which is a string and you create sub models, like
class Admin < User
end
Class CMS < User
end
etc....
Also, put all the common attributes in the User model
Look at these links for an in-depth explanation. STI is the solution. That much is sure
http://samurails.com/tutorial/single-table-inheritance-with-rails-4-part-1/
devise and multiple "user" models
Unique IDs between Users and Admins with Devise Rails
Rails 4 Devise Multiple User Models STI
Stackoverflow ppl has already dealt with STI extensively!
Hope these helps!
Use STI mechanism...
or you can separate all tables with use of devise
Lets assume a website whether students, lecturers can login.
This can be done in two ways:
User model will be there, and user_type field ensure whether he is student or lecturer. But, in this way, if a student takes username 'a', then lecturer cant take same username 'a'. Since they both are different, for example like /profiles/lecturers/a. Here, user model says 'a' already exists, but that belongs to Student but not lecturer, so what should profiles/lecturers/a say? weird, right?
Here, There wont be any user model. Separate Lecturer and Student models with separate usernames. Offourse,we can have a common user model with common things like name, address, country. But, username should not be in usermodel. They should be part of Student, Lecturer.
Just not getting what to start with ?
What do you guys suggest ? 1 or 2 ?
Thanks.
I think it depends on whether you really want the username to be unique. Of course you could always have the unique field be an email and that could solve the problem.
Generally, for simplicity its probably easiest to just go with one User Model (differentiated by email for example) and then use a gem like cancan (https://github.com/ryanb/cancan) to make different roles.
For authentication you can also take at many excellent gems that fit that bill, most notably:
Devise https://github.com/plataformatec/devise
Sorcery https://github.com/NoamB/sorcery
I would lean towards #1 but use STI (single table inheritance) - its not always the best solution, but might be a good fit here, at least it is worth experimenting with
something along the lines of:
use devise and generate a User model and table, let devise handle all user authentication - it will use users.email as the login by default, go with that
add a 'type' column (string) to your user table for STI
add a 'nickname' column to the user table, show that in the UI, no need for it to be unique across Lecturer and Student
implement Lecturer and Student models which inherit from User
class User < ActiveRecord::Base
# all of the devise code
# ...
def is_student?
type == "student"
end
# ...
class Lecturer < User
# ...
class Student < User
# ...
Devise will inject the current_user method in your controllers, you might need/want to override it. Normally it would return a User object, you can use becomes to cast it to the appropriate sub-class - see http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-becomes
def current_user
return nil unless #current_user
if #current_user.is_student?
#current_user.becomes(Student)
elsif #current_user.is_lecturer?
#current_user.becomes(Lecturer)
else
#current_user
end
end
or don't mess with current_user at all, instead add in your own current_student and current_lecturer methods
# nil if not a student
def current_student
current_user.becomes(Student) if current_user.is_student?
end
NOTE: none of this code has been tested, your milage may vary
I don't think there is a simple answer for this. It will be really simple and won't matter so much which route you take if your application only have Student and Lecturer.
However, what happen when, you are required to have Classroom? A classroom can have multiple lecturers and multiple students. It is still quite simple to query either Lecturer or Student from Classroom right? What happen when you want to look for students that have classes given lecturers? Then you have Faculty, Course, Examination, Grade, GPA, then may want to define which lecturer can create what etc etc. Surely all of this can be solved using those SQL techniques rails handily provides but what are the trade-offs?
So I guess my answer is unless you have taken all those into consideration there is no right way.
I have installed Devise and created Users and also Admins using Option 1 from this tutorial https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-role
Now I need a little help. When adding the Admins it creates a different table, and the potential arises that the admins and regular users could have the same ID's.
So how exactly do I got about grabbing information from users and admins? Say for example I want to display all users? Do I have to traverse the users table and then the admins table?
Or if I am displaying a post. How will I know which table to look for to get the user or admin info?
I know I can just add a role column to the users table but I wanted to avoid this.
I hope this makes sense haha
I highly recommend using the Single Table Inheritance (STI). You could do the STI by adding a column named type with a string datatype in the users table and create an admin model as well as a normal_user model both models will inherit from the user model of the devise gem.
class NormalUser < User
end
class Admin < User
end
The type column is a reserved word which will hold a value either NormalUser or Admin according to the user type you created.
To create an admin use Admin.create(...) and to create a normal user use NormalUser.create(...) where the dots are the attributes of the Admin and the NormalUser
I'm creating a Rails app for students and high schools and I'm having some trouble with my User.rb.
I want to have a user model to be used for logging in, but having that user have many roles. The tricky part is that I want users that have a student role to have_one student page, and those that have a role of principal to have_one high_school page.
The students and also nested in the high_school so the entire thing becomes a big mess.
So my question(s): How do I limit a user to only creating one student / high school to represent them? Also how would I nest this student pages inside the highschool without screwing up the user system?
My environment: Rails3 and Ruby 1.9.2dev
Thank you!
Follow up: Would it be possible to put the name of the high_school in the subdomain? That would make the url look like
highschoolname.mysite.com/students/eric-koslow
I'd suggest polymorphic association to user_representations. It'd hold info about which high_school object or which student_page to associate the appropriate user to.
You can made a validation to avoid the multi-creation.