Rails has_many and has_many through - ruby-on-rails

I am confused on how to go about approaching this. I am connecting users and groups through the membership model, but I also want users to be able to create new groups. Clearly a group must then belong to a user, but the groups also belong to users through the memberships table.
I have this in my user.rb file, but I feel it is wrong. Do I remove the first one and just have the through one? How do I work in the creator of the group in that case?
class User < ApplicationRecord
has_many :groups
has_many :groups, through: :memberships
end
In other words, the user is a member of many groups, but also the creator of many groups. The memberships table only has two columns (group id and user id). The user id in this column is used to store users who are members of that group. I am stuck on what to do about the user who created the group.

You should have two relationships between Groups and Users. One reflecting the fact that a user created a group, and one that a user belongs to a group. You can reflect this idea by configuring the naming of your relationships. You will have to add a user_id field to your Groups table as well.
class User < ApplicationRecord
has_many :created_groups, class_name: "Group"
has_many :memberships
has_many :groups, through: :memberships
end
class Group < ApplicationRecord
belongs_to :creator, class_name: "User"
has_many :memberships
has_many :subscribers, through: :memberships, source: :user
end
class Membership < ApplicationRecord
belongs_to :user
belongs_to :group
end

Related

Get items with Rails relations

I have two models with a relation like this:
class Ticket < ActiveRecord::Base
belongs_to :group
end
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
has_many :tickets, as: :assignable
end
class Group < ActiveRecord::Base
has_many :tickets, -> { order(:created_at) }
has_and_belongs_to_many :users
end
I need to get all tickets belonging to the same groups the user has.
How can I accomplish that? Thank you so much!
As things stand, your relations are incomplete and so Rails won't work properly. If User has_many Tickets then Tickets must belong_to (or at least has_one) User. Alternatively, User can have_many Tickets through Group, which seems more likely in this case.
However, even then, it's not clear what your Group model is doing. Particularly, it's not clear how you intend it to relate to User - this looks like quite a complex relationship.
To start with, though, try and set the models up like this:
class Ticket < ApplicationRecord
belongs_to :group
end
class Group < ApplicationRecord
belongs_to :user
has_many :tickets, dependent: :destroy
end
class User < ApplicationRecord
has_many :groups, dependent: :destroy
has_many :tickets, through: :groups
end
(You'll see that I've also inherited these models from ApplicationRecord, which is how I've always done it.)
If you set it up as above, you can get your ticket records with a simple #user.tickets.
If this works, you can then add the extra HABTM relationship for Groups and Users. But be aware that HABTM relationships can be complex and there are good and bad ways to use them.
(If the primary relationship you really want is Groups > Users > Tickets then let me know and I can adjust accordingly.)

Multiple has_many through relationships Rails

I'm still learning how to use has_many and has_many through relationships effectly. I am currently building a system where I would like users to be able to access certain maps that they are added to.
The map model is what I need the user to be able to access if they are apart of a certain group.
class Map < ApplicationRecord
has_many :rows
has_many :mapgroups
has_many :groups, through: :mapgroups
end
Since a user can belong to many groups I have a has_many through relationship
class Usergroup < ApplicationRecord
belongs_to :user
belongs_to :group
end
class User < ApplicationRecord
has_many :usergroups
has_many :groups, through: :usergroups
end
class Group < ApplicationRecord
has_many :usergroups
has_many :users, through: :usergroups
has_many :mapgroups
has_many :maps, through: :mapgroups
end
I thought about making a mapgroup model to take care of this but, so far, I am not so sure this is going to work.
class Mapgroup < ApplicationRecord
belongs_to :map
belongs_to :group
end
I am looking for a method to check to see what groups the user is apart of and then, based on those groups, give the user access to the corresponding maps. Am I on the right track with the relationships? How could I do this?
If you want to use MapGroup model only for keeping users an map connected (ModelGroup has only foreign keys on Group and Map) it's not the best approach. In this case it's better to opt for has_and_belongs_to_many assosiation. It will let you to assosiate Groups and Maps without creating useless model.
A has_and_belongs_to_many association creates a direct many-to-many connection with another model, with no intervening model.
class Group < ApplicationRecord
...
has_and_belongs_to_many :maps
end
class Map < ApplicationRecord
...
has_and_belongs_to_many :groups
end

Association for model - has_many :through

I have three models - Company, User and CompanyUser. The associations are as follows.
Company.rb
has_many :company_users
has_many :users, :through => :company_users
User.rb
has_many :company_users, :dependent => :destroy
belongs_to :company
CompanyUser.rb
belongs_to :company
belongs_to :user
For fetching current_user.company, what moddifications are to be made in the model association?
Any help would be appreciated.
It should be:
has_many :companies, through: :company_users
A has_many :through association is often used to set up a many-to-many
connection with another model. This association indicates that the
declaring model can be matched with zero or more instances of another
model by proceeding through a third model.
So if you are creating three models and making a has_many :through association I believe that User will have many Companies and Company will have many Users.
But if you need that the user belongs to only one company instead of creating the third model save the company_id in the users table itself.
Update:
Now as your scenario is A company can have may users and User belongs to a single company, you need two models: User and Company. Your User model should have an attribute company_id and then company_id should be saved in users table only. Then the associations as follows:
class User < ActiveRecord::Base
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :users
end
Then you can do current_user.company
You can get more information on associations in the RailsGuides
According to the associations you have taken,
user already have as association with the company through the Company User model, so user may have many companies according to your associations.
so,
class User < ActiveRecord::Base
has_many :company_users, :dependent => :destroy
has_many :companies, :through => :company_users
end
current_user.companies will give you the companies.
But if you need only one company for a user then,
class User < ActiveRecord::Base
belongs_to :company
end
take belongs_to company and save company_id in users table,
then you can call,
`current_user.company`
According to your logic,
I think you may need to create a new variable session current_company_user which is object CompanyUser.
And then, to fetch company by :
current_company_user.company

Rails group model that can own groups that can own users

I'm trying to figure out how to model groups and users for my app, and I'm having trouble figuring out the proper way to do it.
I have users, and I have admins. I don't have a model for groups yet. I'd like a group to be able to own multiple users, and users could have multiple groups. To complicate things further, groups could have multiple users through other groups.
class Group
belongs_to :admin
has_many :users
has_many :users, through: :groups
end
class User
belongs_to_many :groups
end
class Admin
has_many :groups
end
I think I need a membership table. Then each user would be connected to a group through a membership. But then how could I connect groups --> groups --> users?
class Membership
?
end
A couple pointers here.
belongs_to_many is not a thing, at least as of the latest version I'm familiar with. Maybe you mean has_and_belongs_to_many or probably has_many :groups, through: :memberships. I'm going to use this latter form below.
In order to use the through :groups option in the Group class, you first need to define a :groups association. If all you are trying to define it as is any other Group that has a User that is a member of both that and this Group, then you can do this easily:
class Membership
belongs_to :user
belongs_to :group
end
class User
has_many :memberships
has_many :groups, through: :memberships
end
class Group
has_many :memberships
has_many :users, through: :memberships
has_many :groups, through: :users
end
You might want to rename this association to be a little less confusing:
has_many :connected_groups, through: :users, source: :groups
Now you want to define another users association on Group that represents the users of any connected group. You need a different name, you cannot meaningfully define two associations of the same name (how would you access one vs. the other?). So I'd suggest using the names connected_groups and connected_users, or something similar:
class Group
has_many :memberships
has_many :users, through: :memberships
has_many :connected_groups, through: :users, source: :groups
has_many :connected_users, through: connected_groups, source: :users
end

Triple join in Ruby on Rails

I have question regarding associations in Ruby on Rails. In the application there are projects, users, roles and groups. The project belongs to a group with users, a user can belong to many different groups but can only have one specific role within that group. For example:
In one group the user is the project owner, but in another group he is a writer.
What is the best way to implement this using the built in functions in Rails?
Thanks
Here is a very quick set of models that should fulfill your requirements:
class User < ActiveRecord::Base
has_many :group_memberships
has_many :groups, :through => :group_memberships
end
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :role
belongs_to :group
end
class Role < ActiveRecord::Base
has_many :group_memberships
end
class Group < ActiveRecord::Base
has_many :group_memberships
has_many :users, :through > :group_memberships
end
Basically there is a join table that has a user, group and role id in it. I'll leave the migrations as an exercise for the questioner

Resources