I'm trying to implement a Group system where a User can create a Group and other Users can join the Group.
class User < ApplicationRecord
has_many :groups
end
class Group < ApplicationRecord
belongs_to :owner, :class_name => "User"
has_many :members, :class_name => "User"
end
When checking the owner, I can successfully use:
<% if current_user == #group.owner %>
But I'm unable to check the members of the group with:
<%= #group.members.count %>
As I run into an error:
SQLite3::SQLException: no such column: users.group_id: SELECT COUNT(*) FROM "users" WHERE "users"."group_id" = ?
I think it has something to do with how my Users are setup, but can't figure it out.
Also, once I'm able to have a list containing all the Users that have 'joined' the Group, how do I add/remove Users from that?
Thanks.
There are two possibilities here:
One User can belong to Many Groups
If one user will belong to only one group which your association says then you need to add group_id attribute to the User model or users table which will identify in which group the user belongs to. Currently you don't have that column that is why it is throwing an exception. Regarding the owner you have a owner_id in you Group table which gives you the owner which is an User object.
User - group_id
Group - owner_id
But this way you will have only one group associated with the User, so your has_many :groups is of no use in User model. To have multiple you need another table in between:
One User will belong to only One Group
If one user can belong to multiple groups then you need to create one more model like UserGroups which will have user_id and group_idand the associations will go like this:
class User < ActiveRecord::Base
has_many :user_groups
has_many :groups, through: :user_groups
end
class Group < ActiveRecord::Base
has_many :user_groups
has_many :users, through: :user_groups #This can be members also using `class_name`
end
class UserGroup < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
A User also belongs to a group (you forgot that).
In your group schema you need a group id so that once a group is created other users can join that specific group. Both owner and member should be of type "references" in your schema. With that you should be fine.
Related
I'm doing a project and I'm going through the permissions, my database model is more or less like this: I have a has_many through relationship, between user (done with Devise) and groups (made with scaffold name description: text), through the membership table, and the groups with activities (another basic scaffold), through permissions, which has:
1) activity_id: references
2) group_id: references
3) c: boolean (to create, if c = true, the group the user is in can create activities)
4) r: boolean (for reading, if r = true, the group the user is in can see activities)
5) u: boolean (for update, if u = true, the group in which the user is can edit activities)
6) d: boolean (to destroy, if d = true, the group the user is in can delete activities)
7) o: boolean (for own, if o = true, the group the user is in can only manage the activities that he has created)
I need:
1) That there is some parameter so that one group can make users crud in another group, that is, administer it.
2) From the form, when creating a group, you can manage the permissions of c, r, u, d, o on the different activities that may exist.
3) That the user can only manage the things he has created depending on whether o not it is true or false.
I think your models should be like this.
class User << ApplicationRecord
has_many :owned_groups, class_name: "Group" #The groups he has created
has_many :memberships #Association to groups he has joined
has_many :groups, through: :memberships #The groups he has joined
end
class Group << ApplicationRecord
belong_to :owner, class_name: "User" #The user who created the group. He sets premissions.
has_many :group_activities #Association to activities
has_many :activities, through: :group_activities #The group activities
end
class Activity << ApplicationRecord
has_many :group_activities #Association to groups
has_many :groups, through: :group_activities #The groups where this activity belongs
end
class GroupActivity << ApplicationRecord
belongs_to :group
belongs_to :activity
end
class Membership << ApplicationRecord
belongs_to :user #This user is member of...
belongs_to :group #this group.
# This table should have the
# permissions for this user
# in this group (create activities, etc.).
# The Owner of the group can define these permissions
end
I can continue improving the answer if you think this models are correct.
To answer your first question - I hope your model may looks like this
class User < ActiveRecord::Base
has_many :memberships
has_many :activities, through: :memberships
delegate :c, to: :memberships #this way you can access c value with user
end
so
user = User.find_by (id: 1)
user.c # will return the value true/false
To answer your second question - I need a bit clarification on this line
I also need to know how to create this relationship from the form
Relationship between which models??
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
I have the following setup in my database. We have users. Each user has many entries. Users also belong to organizations, through a table called organization_users.
class User < ActiveRecord::Base
has_many :entries
has_many :organization_users
has_many :organizations, :through => :organization_users
end
class Entry < ActiveRecord::Base
belongs_to :user
end
class Organization < ActiveRecord::Base
has_many :organization_users
has_many :users, :through => :organization_users
end
class OrganizationUser < ActiveRecord::Base
belongs_to :user
belongs_to :organization
end
Here's my question: for a given organization, I want to get a list of all the entries for the users in that organization. Is there a nice compact way to accomplish this? I know I can iterate over all users in the organization and get the entries, but I'm not sure if there is a nice rails-y way to do this.
You can do the following assuming you have a foreign key called organization_id in organization_users table as per your Model
Entry.joins(:user => :organization_users).where("organization_users.organization_id = ?", org_id)
Where org_id is the id of the given organization. This will give you all entries of all users in an organization
Try something like that :
my_org = Organization.find(id)
my_org.users.eager_load(:entries)
First you get the organization you want to query. Then via :through association you can directly retrieve all the users for that organization. And last using eager_load, in one query you get all the entries. The result will be an ActiveRecord::Relation.
My app has User. These users belong to one or many groups. Obviously groups can have many users.
How do I do this in Rails?
Is this a has many or a has many through association? What is the name of the third model if it's "has many through"? Nothing seems to make sense. Or is it just something like "group-user-link"?
If I have user_id and group_id in the respective tables, what happends when a User has multiple groups?
Yes there is a way. If you wanted to have many to many relationship you just need a joining table. Say, your user migh belongs to many groups and and groups may belongs to many users.
So you can define a joining table like this:
rails g model user_group user_id:integer:index group_id:integer:index
This will generate a migration file for you and a model user_group.rb
run the migration and put the following things on the other models:
in user_group.rb
class UserGroup < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
In your user model
class User < ActiveRecord::Base
has_many :user_groups
has_many :groups, through: :user_groups
....
end
so in your group model
class Group < ActiveRecord::Base
has_many :user_groups
has_many :users, through: :user_groups
.....
end
And this is how you can achieve your desired relationships.
This is probably a newbie question, but I can't seem to think of a good solution. I have a company table that has_many users through groups that can also be administrators of the company (enabling them to edit the company but only one company per user).
What's the best way to set this up in Rails?
I can't add an admin field to the user table, because it wouldn't discriminate which company he/she is administrating. But if I do a company_id field, what would that relationship look like in Rails (since it's a sort of somtimes_has_one relationship!). I could leave it without a relationship, but that doesn't seem proper...
Thanks in advance for any help!
From what I understand, you have a user which might belong to a company, and if it does, it might actually administer it.
You could setup Group to have for example, company_id, user_id and an admin field (this way you get to know which users belong to which company, and if they also administrate that company)
For a user to belong to just one company you could add a validation for uniqueness per two columns (company_id and user_id)
You could get one company's administrators by doing
class Company < ActiveRecord::Base
has_many :groups
has_many :users, through: :groups
has_many :administrators, through: :groups, source: :user, conditions: ["groups.admin = ?", true]
end
and call company.administrators or company.users for all users
You could also do something like
class User < ActiveRecord::Base
has_one :group
has_one :company, through: :group
has_one :administered_company, through: :group, source: :company, conditions: ["groups.admin = ?", true]
end
so you can call user.company or user.administered_company
and so on...