Ruby on Rails Relationship - ruby-on-rails

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

Related

Rails : has_one and belongs_to same model

Say an admin can be the owner of an account and an account can have many admins. You would have association like the followings :
class Account < ApplicationRecord
belongs_to :account_owner, foreign_key: :account_owner_id, class_name: 'Administrator', optional: true
has_many :administrators
end
class Administrator < ApplicationRecord
# account instance has an account_owner_id that references the administrator "app owner"
has_one :account
# administrator has an account_id on it that references the account he belongs_to
belongs_to :account
That code doesnt work properly because the instance method account defined twice on Administrator clash with each other.
Then I would tend to writte something like this :
class Administrator < ApplicationRecord
has_one :account, as: :proprietary_account
belongs_to :account
to differentiate between the two "sides" of the association.
However this doesnt work either and method proprietary_account is not created
Is there a way to model that with rails associations ? If not how would you create this kind of relationship in a rails app.
You need to create another table called admin_accounts and use the has_many :through association. The admin_accounts table will have two columns, one with admin_id, and one with account_id. You can then associate the two models through that table. More information here: https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

User and Project relationship

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

has_one through association or alternative way?

Not sure how to setup the tables and the relationships for what I'm trying to achieve. I thought I need a has_one through relationship but I saw a few posts advising against that.
What I'm trying to achieve is a shop creates a list of their services and their staff select the services they do from this list.
Here's what I have so far:
class User
has_many :staff
# user and shop have relationship via roles (not shown for simplicity)
end
class Shop
has_many :staff
has_many :services
# user and shop have relationship via roles (not shown for simplicity)
end
class Service
belongs_to :shop
has_many :staff through: :staff_services
end
class Staff
belongs_to :shop
belongs_to :user
has_many :services through: :staff_services
end
class StaffService
belongs_to :staff
# ? has_one :service through: :shop
# ? belongs_to :service
end
I'm not sure how to set the relationship for StaffServices so that a staff is only able to select services from the shop they are a staff member of.
Any help would be appreciated. Thanks!
If I understand you correctly you want a many-to-many associations between Staff and Services. I believe you want belongs_to :service in your StaffService table. This can be simplified to isolate the association you're working with as such:
class Service
has_many :staff, through: :staff_services
end
class Staff
has_many :services, through: :staff_services
end
class StaffService
belongs_to :staff
belongs_to :service
end
I don't mean to suggest the other associations you've got in your example are invalid or wrong in any way--I just wanted to show only the many-to-many part. The associations you already have up there between Shop & Staff, and Shop & Services will allow you to build scopes easily that will restrict the set of Staff and Services involved.
If you haven't already, I suggest giving the Rails Guide to Associations a careful read.

Create has_and_belongs_to_many and belongs_to both

I have to build functionality where a user create a company and then many user can be associated with that company. It will be simple and can be done by has_and_belongs_to_many. But i also have to record and identify the user who has created that company. If you need any other information let me know
Make a separate association for the User representing the 'owner' of the Company:
class Company < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_and_belongs_to_many :users
end
class User < ActiveRecord::Base
has_many :owned_companies, class_name: 'Company', foreign_key: :owner_id
has_and_belongs_to_many :companies
end

User and Team modeling

I have been doing some searching around Google and this site for some ways to go about constructing some models for an application I am working on.
I plan to have Users and Teams. A user can join a team and one team only. A team can obviously have many users. Also, I want to add a 'leader' role inside the team that is assigned to the User who creates a Team but can later be passed on to another User who is already a part of that team.
I have seen some examples of models for something like this and saw a few like this:
class User < ActiveRecord::Base
has_one :team
has_many :memberships
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :team
end
class Team < ActiveRecord::Base
has_many :memberships
has_many :users, :through => :memberships
end
Why is the Membership model necessary? I have seen it in a few examples and I am not sure I quite follow the logic of why it is in there and what it is doing.
Also, if I did something like has_one :leader in the Team model and had the Leader model, would that be considered the best practice for determining a leader in a Team? It seems like a bit much to have an entire model/table for Leader.
The Memberships model is allowing for a many-to-many relationship there. It's acting as the join table. It would allow Users to belong to many Teams and Teams to have many Users.
Sounds like you just want a one-to-many though?
class User < ActiveRecord::Base
belongs_to :team
end
class Team < ActiveRecord::Base
has_many :users
end
I'll have to double check this part but you can use additional parameters to specify the models in your assocation if they don't match up with the name you need. So Team could have a leader that's just a User model.
class Team < ActiveRecord::Base
has_many :users
has_one :leader, :class_name => "User", :foreign_key => "user_id"
end
the rails guides page on associations has a good summary including the part about the :class_name and other options
http://guides.rubyonrails.org/association_basics.html#the-has_many-association

Resources