Create Association on Registration Devise - ruby-on-rails

I currently have 3 models set up:
class User < ActiveRecord::Base
belongs_to :user_type, polymorphic: true
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable, :rememberable
devise :database_authenticatable, :registerable, :recoverable, :trackable, :validatable, :confirmable
end
class Teacher < ActiveRecord::Base
has_one :user, as: :user_type
end
class Student < ActiveRecord::Base
has_one :user, as: :user_type
end
I would like to know what the best way to, upon a user signing up, create either a Student or Teacher, that is automatically associated to the User.
The Student & Teacher models have different attributes, but a User must be either one or the other.
My initial thought was to do the registration through the Student/Teacher Model, and then call devise's create method within the Student/Teacher create method, although I'm not entirely sure how to do that as well.
As an aside, one this is set up correctly, how would I go about setting different redirect paths after sign in depending on whether the user is a Student or a Teacher?
Any help is appreciated, thank you!

I don't know what is the condition for it to be student or teacher, but you could do that on "before_create" callback.
For example, something like this on user model:
before_create :assign_role
def assign_role
//if condition, teacher.create or student.create
end
But have you considered to use inheritance, instead? Put User as superclass of student and teacher, and on then, instead of
class Teacher < ActiveRecord::Base
it would be
class Teacher < User
then on teacher/student model you would put the particular attributes and methods you want. I think it's more clean and ellegant. Good luck!

Related

Rails relationship for a single user role

i'm currently working on building a site like freelancer using RoR, but i'm stuck somewhere, my user table which was generated with devise has a role column which can be admin, client or freelancer. Also i have a skills table which belongs to user but i don't want every user to have skills except from the users with the role of freelancer, how do i go about this, i'm currently using cancancan for user authorization and devise for authentication, is roles the best solution to this or STI and how would you advice me to approach this problem, here's an example code
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_roles
has_many :skills
has_many :skills, through: :user_skills ## I don't want all users to have skills except the users with the role of freelancer
has_many :roles, through: :user_roles
def role?(role)
roles.any? { |r| r.name.underscore.to_sym == role }
end
end
thank you in anticipation.
You could do something like this:
class Skill < ApplicationRecord
belongs_to :user, -> { where role: 'freelancer' }
end
Keep in mind that this would save the skills for any role, but they would be visible only for freelancer.
You could also use cancancan to check whether the user is a freelancer.

What steps do I need to take to make this one-to-many relationship into a many-to-many?

I've seen some other posts about this but they're dealing with a version of rails that I'm not using (I'm VERY new to rails), and I have this set up:
class ProjectModel < ActiveRecord::Base
belongs_to:user
And:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :project_models
I need to know what steps I have to take in order to change this into a many-to-many migration.
Notes: This is for a group project and its my part to set it up so that the projects have a list of users assigned to them, and this list needs to be able to have members added to or deleted from, so I'm not sure whether there needs to be a has_and_belongs_to_many or a has_many:through set up.
Any other info that you could give me would be greatly appreciated but since I'm so new to rails I don't even really know how to do this migration (I only know how to do a one-to-many migration using something like AddAuthorRefToBooks authors:references, if we were working with an example like that).
You need to add an intermediary Model e.g.
class ProjectParticipant
belongs_to :user
belongs_to :project
end
class Project
has_many :project_participants
has_many :users, through: :project_participants
end
class User
has_many :project_participants
has_many :projects, through: :project_participants
end
You can start out with the following so it will also generate the migration you need to create the table.
rails g model project_participant project:references user:references
or the equivalent
rails g model project_participant project_id:integer user_id:integer

Should I use new or edit action on model that inherits from other model

I have the following models:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Teacher < User
end
class Student < User
end
Users login in through a devise form that creates a user. I want to have two kinds of profiles like teacher and student though and they can be both at the same time as well.
So when I go to create a new Teacher I am just going to teachers/id/edit form and updating the teacher that inherits from user. Should I do this or can I go to teacher/new ? and create a teacher from there when I have my models inherit like I do?
Don't use inheritance here. Create separate TeacherProfile and StudentProfile tables, and make one-to-one associations:
class TeacherProfile
belongs_to :user
end
class StudentProfile
belongs_to :user
end
class TeacherProfile
has_one :teacher_profile
has_one :user_profile
end
Then just follow the standard protocol. Go straight to edit, check if the profiles exists, and create it if it doesn't, something like this:
def edit
#profile = TeacherProfiler.where(user: current_user).first_or_create
end

Multi-level Association in Rails?

I am working on a medical application. In it, I have associations between users and clients (obviously), and an association between users and treatments, and users and settings (for a settings table).
But the tricky part here is that the client also has to be associated to the treatments table, because they are the ones that have the treatments on their record. The user is simply the one administrating all of the above. And also we have patients who are associated to clients, so it will need to be multi-layered. So owners have clients who also have patients. And patients have treatments as do Clients and do owners.
It seems really complex to me and I am having a hard time getting anything beyond user working. I am using the basic relationship setup in Rails (i know very little about rails). I am using #treatment.user = current_user on the create method, and then simply associating the tables needed with a user_id. I put a client_id on the treatment table, but that won't work will it?
Do I need a polymorphic association (not sure what that is though)? OR do I need seperate tables to do all of this matching?
Thanks.
Code:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation,
:remember_me, :role
validates :email, presence: true
has_many :clients
has_many :settings
has_many :treatments
ROLES = %w[admin receptionist practitioner]
def role_symbols
[role.to_sym]
end
def to_s
email
end
end
I am not totally sure yet, on what your problem is.
But since you mentioned you are not familiar with Rails, this might help you:
Have a look at the has_many :through relation (also available as has_one :through)
So you could probably do something like this:
# patient.rb
class Patient < ActiveRecord::Base
has_many :treatments, :through => :client
end

How can I move "has_many" associations and fields from one collection to another?

I'm quite new to RoR. Sorry if I'm using wrong terminology or the answer is obvious.
Initially I had one model for users as follows,
class User
include Mongoid::Document
devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:token_authenticatable,
:omniauthable
has_many :foos
field :name, :type => String
# Some other company fields
....
end
class Foo
include Mongoid::Document
belongs_to :user
...
end
This initial User model used to represent a company.
Then I decided to add another model which will have a different role from the initial User model, so I started using polymorphic associations and moved the necessary fields from User to Company model. I also added a Manager model which is not directly related to Company. I basically use User model for devise.
class User
include Mongoid::Document
devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:token_authenticatable,
:omniauthable
belongs_to :rolable, :polymorphic => true
end
class Company
include Mongoid::Document
has_one :user, :as => :rolable
has_many :foos
field :name, :type => String
# Some other company fields
....
end
class Manager
include Mongoid::Document
has_one :user, :as => rolable
end
class Foo
include Mongoid::Document
belongs_to :company
...
end
Everything seems to work fine so far for the new user registrations. However, there is the old database I have to convert. What confuses me is essentially the has_many association that I had before. I already implemented migration (using this gem, https://github.com/adacosta/mongoid_rails_migrations) to move the fields from User model to Company model, but again I couldn't figure out how to deal with the associations.
You are not required to run your migration if you don't need to transfer the information from your old database to your new one.
MongoDB can have some useless keys on document, there are no problems. The only problem you can have is to have extra octet saved on your database.

Resources