ruby on rails -- can two Models belong to each other? - ruby-on-rails

My group is making a Project Management System for our course, and it's my job that when a user is logged in, that they see the projects they are part of, and also that the projects listed have a members list of current members of that project.
(Also will need an add/delete member function later)
My question is, since the rest of the group have already set it up so that Projects belong to Users, is it possible to have Users belong to Projects in order to set up this member list and do what I'm talking about?

The relation you are describing is not one-to-one:
when a user is logged in, that they see the projects they are part of
This implies that a user can have several projects. You also specified:
[project has a] list of current members of that project
This implies that a projet can have several users.
In conclusion, you need a many-to-many relation between your User and Project models.
This is a basic many-to-many relationship in Rails:
class User < ActiveRecord::Base
has_many :user_projects
has_many :projects, through: :user_projects
class Project < ActiveRecord::Base
has_many :user_projects
has_many :users, through: :user_projects
class UserProject < ActiveRecord::Base
belongs_to :user
belongs_to :project
validates :user_id, :project_id, presence: true
The UserProject model is a join table. What I have done in my code is an explicit has_and_belongs_to_many, which let you have more control over the join table. (example: add a role column in the UserProject table, containing data like project_creator or simple_member)
The UserProject model could be named Membership to be more explicit. I used both models' name to make UserProject, as we usually do in Rails' naming convention.

Related

Rails how to access users status on project level

I have two models User and Project which are in has_and_belongs_to_many association
The user model has a column status
i can access the status of a user who is in project like
project.user.status
but a user can be in different projects i want his status to be on project level instead of on his id
If I understand your question correctly, the problem is that you need to associate the status of the user to one of potentially many projects that the user is associated with, but you are associating a single status to a single user instead of the project.
In that event, you need to abstract this association to an additional model, for instance "UserProjectStatus" which would be associated with both the User and the Project. You can do this using the has_many, through association. This would end up with something along the lines of:
class Project < ApplicationRecord
has_many :user_project_statuses
has_many :users, through :user_project_statuses
end
class UserProjectStatus < ApplicationRecord
belongs_to :user
belongs_to :project
end
class User < ApplicationRecord
has_many :user_project_statuses
has_many :projects, through :user_project_statuses
end
There is a good overview of this any many other Rails ActiveModel associations at https://guides.rubyonrails.org/association_basics.html#the-has-one-through-association.
Hope this helps!

Compare data from two tables in rails and post in third

I have three models; User, Project, Skill. I have associated user & skill and skill & project. Now I want to assign a project to users based on skill, if they have the skill needed for the project they can be assigned, otherwise can't. No limit on how many users can work on one project.
I am working on rails. Need a start to the problem.
One method to get a view of available projects/users would be to add has_many :through to each using the skills table....
def User < ActiveRecord
belongs_to :skill
has_many :available_projects, through: :skill, source: :project
end
def Project < ActiveRecord
belongs_to :skill
has_many :available_users, through: :skill, source: :user
end
Then call the associations as needed...
user.available_projects
and...
project.available_users

has_many through relation in active model serializers Rails API

I have many to many relation between users and projects through user_project. I know I could simply add has_many :projects in User Serializer (and vice versa in project serializer) to nest projects inside users.
But I also have a few additional fields in user_projects table (eg. start and end dates for user's participation in a corresponding project) and I have no idea what is the correct way to include them in the returned json. Should I create a special serializer for projects that are returned inside user with start_date included as a project's attribute or there's another way to do that?
The best way to do this would be to establish a 'has-many-through' (HMT) relationship between the user and project models and create a serializer for relationship's model.
class UserProjectSerializer < ActiveModel::Serializer
...
end
This will then be used in the UserSerializer via:
has_many :users_projects
The reason is that the relationship between the models contains additional data.
To implement the HMT, you'll need to create the user_projects model and define the HMT relationship in the related models:
users_project.rb
class UserProjects < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
user.rb
class User < ActiveRecord::Base
has_many: users_projects
has_many: projects, through: :user_projects
end
project.rb
class Project < ActiveRecord::Base
has_many: users_projects
has_many: users, through: :user_projects
end
I have had a similar problem before and I made use of rabl. There is a good tutorial on railscasts to help you get started.

Ruby on Rails: choosing between has_many :through and simply has_many

I'm trying to create a linkedin clone, in which users can have several skills. They can also have descriptions for each skill and choose whether the skill is their primary skill or secondary skill (they can have only one of each).
I can't decide whether to just use a has_many or has_many :through.
If I use has_many
class Skill < ActiveRecord::Base
belongs_to :user
validates :description, presence: true
validates :name, presence: true
end
class User < ActiveRecord::Base
has_many :skills, dependent: :destroy
end
Skills table will also have columns primary and secondary, which are booleans.
If I use has_many :through
class Skill < ActiveRecord::Base
has_many :users, through: :users_skills
has_many :users_skills
end
class UsersSkill < ActiveRecord::Base
belongs_to :user
belongs_to :skill
end
class User < ActiveRecord:Base
has_many :skills, through: :users_skills
has_many :users_skills
end
Here, I will have the primary and secondary boolean columns in the UsersSkill model.
Which do you think would be a better choice?
Based on both your stated requirements:
I mainly want people to be able to type in a skill to search for
people with that skill
 
They can also have descriptions for each skill and choose whether the
skill is their primary skill or secondary skill (they can have only
one of each).
And on just my understanding of the meaning of the models, i.e. that a "Skill" is something which doesn't necessarily belong to a single user -- I'd go with has_many :through.
Reason for this is that the skills are things that stand on their own (and as you said, you want to be able to search for them). Just because one person lists, say, "Scrubbing Floors" as their primary skill, and another as their secondary skill, doesn't mean you should have two entries with "Scrubbing Floors". Have a single Skill for it, and use UsersSkills to assign it to multiple users, along with any information specific to that user's instance of the skill.
You can put the primary/secondary ranking on the users_skills table. The existence of this model will also save you a lot of effort in the future should you ever need to expand the information stored in these mappings.
The bottom line is that the choice depends on one piece of functionality of your system - whether a users' skills are specific to them, or part of a wider group
The has_many relationship will be good if your user will add their skills themselves
The has_many :through relationship will be good if your user's skills can be selected from a wider pool
--
System
You have to remember that since Rails is object-orientated, the setup of your ActiveRecord associations is primarily based on the association of the objects in your system.
many-to-many associations are primarily based on the sharing of objects between two models; whilst one-to-many associations are the result of a model having lots of dependent data
To make the decision, I would simply look at what you've got. If you want to pre-populate the skills, as per the likes of LinkedIn, go for the has_many :through

How to implement projects with project admins in Rails

What I'm looking for is an appropriate way to set up a system where users can create projects and therefor become the admin of that project. The user can then add other admins to the project. Finally, other non-admin users can join the project.
I want to be able to verify whether a user is an admin of a project to check whether he has edit/update privileges. Any thoughts?
I figure I'll probably have a users_projects table and a projects_admins table, but I can't figure out how that translates to Rails relationships....
Thanks!
Ok, I will give it a try, but without too much code here in.
I see here 3 models:
User
Project
ProjectAdmin
The first 2 are simple models, with some attributes. The third one is the relation between the two and will be a n:m relation. So it is best to use the has-many-through relation here.
class ProjectAdmin < ActiveRecord::Base
belongs_to :project
belongs_to :user
end
class User < ActiveRecord::Base
has_many :project_admins
has_many :projects, :through => :project_admins
end
class Project < ActiveRecord::Base
has_many :project_admins
has_many :admins, :through => :project_admins
end
Of course you have to create additionally the 3 tables by migrations, and add later a similar relation for project users, named then ProjectUser as model. Have at least a look at the rails guide about relations, section "has-many :through".
To add the creator to a project, this should be a one-one relation between the two, so it should be sufficient to have:
class Project
has_one :creator, :class_name => "User"
end
(and of course the creator_id in the migration)

Resources