User and Project relationship - ruby-on-rails

So I have a User model created with devise and a Project model. A Project should have one Project owner and project members. So now I have no idea how to create the relations in my models.
What I have tried is have in my User model has_many :projects and in my Project model belongs_to :user but the problem with this is that the project is attached to only one User so i can't add any other users to it.
I tried changing it so that Project has_many :users but this causes my registration with devise to stop working since a user should belong to a project.
Something else I thought about doing is creating a class ProjectOwner and a class ProjectMember and then set that a Project has_many :ProjectMember and has_one :ProjectOwner. And set that a user has_many :ProjectMember and has_many :ProjectOwner since a User can be a project owner in many Projects and be a ProjectMember in others.
Or can I just set that a Project has an attribute of type User called ProjectOwner and another attribute of type User array that named ProjectMembers?
Since I'm pretty new to RoR, I'm not sure what is the right approach for this kind of situation.

What it looks like is you want a User, Role (with ProjectOwner and ProjectMember by STI), and Project
class User < ApplicationRecord
has_many :roles
has_many :projects, through: :roles
end
class Role < ApplicationRecord
belongs_to :user
belongs_to :project
#Code that applies to both project owners and members
end
class ProjectOwner < Role
#project owner specific code
end
class ProjectMember < Role
#project member specific code
end
class Project < ApplicationRecord
has_many :project_members
has_many :members, class_name: "User", through: :project_members
has_one :project_owner
has_many :owners, class_name: "User", through: :project_owner
end
Check out this article to help set up single table inheritance

Related

Dilemma to choose the association for following usecase in rails model association

In a playstation app I have a User model, which already has has_many through association with roles and user_roles. Now our requirement asks us to create a team model, which has one captain and that captain is a user (one record of user model) and at the same time, a team has many users as players. I implemented the scenario with the following way
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles, :dependent => :destroy
belongs_to :team
end
class Team < ApplicationRecord
has_one :captain, class_name: 'User' , foreign_key: 'captain_id'
has_many :users, dependent: :destroy
end
My problem is that I am not able to create a user without a team. When I am creating a new user it is asking team must exist. Our plan is to create a user and then we will assign each user as players and out of them, one will be a captain. So please guide me if my thought process is wrong about the use case and also suggest me the perfect association style for the use case.
Starting from Rails 5, belongs_to association validates presence by default. You can change it with optional option:
class User < ApplicationRecord
belongs_to :team, optional: true
end

What is the alternative for accepts_nested_attributes_for in the belongs_to model activeadmin resource?

I have a memberships resource and it belongs to user and club. I want to access the parent attributes i.e for club and user and I read that accepts_nested_attributes_for is used for parent side of a relationship. What should I write in my membership model?
I have searched about it both in stackoverflow and activeadmin docs but I did not get a thorough explanation about solving my problem...
My membership model is:
membership.rb
class Membership < ApplicationRecord
require 'csv'
belongs_to :club
belongs_to :user
end
Also what should i write in my membership resource which I have already registered with AA...
You can mention the following :-
1) has_many: memberships #in user model
2) has_many: memberships #in club model
This will help you access parent attributes from child model :-
membership.user, membership.club
Also, you can mention accepts_nested_attributes_for: memberships in user model.
When you write this, you can then build a common form for user and membership and modify both of them simultaneously. To achieve this, you will have to allow membership attributes in users_controller.rb.
The following should work(Similar question):
class Club < ApplicationRecord
has_many :memberships, :dependent => :destroy
has_many :users, :through => :memberships
accepts_nested_attributes_for :membership
end
class User < ApplicationRecord
has_many :memberships, :dependent => :destroy
has_many :clubs, :through => :memberships
accepts_nested_attributes_for :membership
end
class Membership < ApplicationRecord
require 'csv'
belongs_to :club
belongs_to :user
accepts_nested_attributes_for :club
end

multiple has_many through with the same model rails

I am trying to set up the model structure that has a User model Project model along with two join tables setup as has_many through to manage two specific aspects of the Project, ProjectManagers and ProjectMembers.
I can setup two has_and_belongs_to_many but it doesn't feel very railsy.
Right now, this is what I have and I'm unsure of how to proceed to use multiple has_many through (Project Manager, Project Member) both referencing User model.
Would a nested through be the way to go even if a Project Manager will not always be part of the Project User table?
project.rb
class Project < ApplicationRecord
has_many :project_members
has_many :users, through: :project_manager
end
user.rb
class User < ApplicationRecord
has_many :project_managers
has_many :users, through: :project_managers
end
project_manager.rb
class ProjectManager < ApplicationRecord
belongs_to :project
belongs_to :user
end
project_member.rb
class ProjectMember < ApplicationRecord
belongs_to :project
belongs_to :user
end
I don't see any problems with what you're doing. There are other options, but this approach should work as you want. Have you tried it? I'd do something like this.
class Project < ApplicationRecord
has_many :project_members
has_many :project_managers
has_many :members, through: :project_members, :class_name => User.to_s
has_many :managers, through: :project_manager, :class_name => User.to_s
end
Another approach, since the join tables are similar is to subclass them and add a type column to the join table. Not necessarily better than what you're doing.
You could also create a project_users table (don't separate members and managers) and include a "role" column. A scope on project_user.rb would bring back managers or members.
Personally, I would go with your approach. Managers will likely have different auth and have relationships with other objects. It's simpler to query and less likely to make a mistake.
And, I wouldn't recommend a has_and_belongs_to_many, you're likely to add other columns to the join table and you'll be glad you have the model.

Ruby on Rails Relationship

I am currently building a registration system which will need to create both a user and an organization. The Organization needs to have an Owner or System Admin. I believe my second option is best as I can create the Organization, a Sys Admin Role and a User without any circular database issues. My fear with the First option is that an Organization is owned by a user and that user also belongs to that organization.
First --
Class User
belongs_to :organization
belongs_to :role
has_one :organization_as_owner, class_name: "Organization", foreign_key: "owner_id"
Class Organization
belongs_to :owner, class_name: "User"
has_many :users
has_many :roles
Class Role
belongs_to :organization
has_many :users
Second --
Class User
belongs_to :organization
belongs_to :role
Class Organization
has_many :users
has_many :roles
Class Role
belongs_to: organization
has_many :users
Using the Second option, I would utilize a permissions table for the Sys Admin, and permit them to add new Roles, etc.. Which setup would you prefer and why? Would using a has_many through on either Option be beneficial?
I would probably set up the relationships like this:
Class User
belongs_to :organization
belongs_to :role
Class Organization
has_many :users
has_many :roles
Class Role
has_many :users
belongs_to: organization
This is assuming all users have only one role. This way, you can make the following calls:
user.role
user.organization
organization.users
organization.roles (this will just collectively list all the roles that the users inside the org have, can always run a uniq! on this if necessary
role.user
role.organization
However, I think you should also probably take a look at the excellent rolify gem that could probably help you do this out of the box: https://github.com/EppO/rolify

How to create multiple relations between the same models

I have a User model
class User < ActiveRecord::Base
has_many :projects
end
and I have a Project model
class Project < ActiveRecord::Base
belongs_to :user
end
Obviously right now each project is owned by a user and there can only be one user per project. I now want to make my models represent another relation between the two models. I want a User to be able to follow multiple Projects, no matter who owns the Project. I know that I am going to have to use a has_many :through and create a join, but I cant wrap my head around how to change the model to keep my current relationship and add the new relationship.
Well, in that case, in your show/index action display all the projects (Project.all) in your project table. This way all users have access to all the projects. Now, in your edit action, use user.projects.all to display projects of that particular user. That should solve your problem, I don't see the need of any further association here.
Update:
This should suffice:
class Project < ActiveRecord::Base
belongs_to :user
class User < ActiveRecord::Base
has_many :projects_followed, :through => :projects
user has_many :projects_owned, :through => :projects
If you don't wish to create two more relations, create just one:class ProjectsSubscribed
belongs_to :project with three fields: project_id, is_owned, is_followed
Try following relation.
class User < ActiveRecord::Base
has_many :followers
has_many :projects, :through => :followers
end
class Follower < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
class Project < ActiveRecord::Base
has_many :followers
has_many :users, :through => :followers
end
Note it:
You can use has_many :through relationship if you need to work with the relationship model as an independent entity. If you don’t need to do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship.
Hope it is helpful.

Resources