Group membership requires confirmation from a group admin - ruby-on-rails

I have a group model and a user model. This is an m to n relationship. The group and user models are joined through a separate membership model.
Some subset of the users that belong to a group are administrators. When a new user tries to join a group by creating a new membership, I would like this action to be confirmed by one of the group administrators before the new user can actually participate in the group.
What is the best way of accomplishing this? My current idea is to have a separate model called permission or invitation that only the group admins can create. A user is only a member of the group when they are part of both a membership and an invitation. This seems like a lot of models for a fairly commonplace task. If this is actually the best approach, some advice on how to go about doing it would be greatly appreciated.
I don't want to use email for confirmation.
I am using Rails 3.1.0.

Why not include the confirmation status in the join model itself? So let's assume you have a User, a Group model and they are joined by a Membership model. Add an attribute "accepted_on" with format DateTime to the Membership model (or just a boolean if you don't care when exactly they were accepted.) Then make a view that lists all the memberships that's only visible to the admins with a link that only they can access which sets the "accepted_on" attribute to Time.current.
In your User/Group model you can then do the following:
class User < ActiveRecord::Base
has_many :memberships, :conditions => 'accepted_on IS NOT NULL'
has_many :groups, :through => :memberships
end
class Group < ActiveRecord::Base
has_many :memberships, :conditions => 'accepted_on IS NOT NULL'
has_many :users, :through => :memberships
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
This way when a new user adds a membership it won't become available until the admin has accepted him (that is, made accepted_on anything other than nil.)

Related

Rails Complex Active Record Relationship

I have a complex active record relationship in mind, and was wondering how exactly I would accomplish it. In essence:
A User can create a Board. A user can then add other users to that board for collaborative editing. Added users form a Team. Each added User has a Role in each board, (Admin, Editor, Viewer).
I was thinking of setting it up this way:
A User has many Boards
A Board has many Users through Teams
A Team has many Users?
The role part has been confusing me. Do I have to set up a TeamUser model which has many Roles, or does each User have many Roles which belong to a Board? Does a Role even have to be it's own model?
What is the most effective way to accomplish my goal?
If a user could belong to many teams and could have many roles, logic could be something like:
You need a join table to supply the N-to-N relationship between User and Board model. But the thing is, when you add a user to a board, you give them a role in that participation. It's a good place to hold role info in that participation. So our UsersBoards join-table transform into the Participation model (Or whatever you like to call it). Our participation model now holds the user, board and role info (All of them is foreign-key).
I didn't exactly understand the purpose of the Team model but I think it's easy to add a user to a team when it's necessary. It will not hurt to our logic.
Also, if you don't plan to add more features in the future, role can be an enum too.
class User < ApplicationRecord
has_many :participations
has_many :boards, through: :participations
end
class Board < ApplicationRecord
has_many :participations
has_many :users, through: :participations
end
class Participation < ApplicationRecord
belongs_to :user
belongs_to :board
enum role: [ :admin, :editor, :viewer ]
end
user = User.first
user.participations.first.board #Board
user.participations.first.admin? #true
user.boards
And you can add helper methods or delegate to models for shortening the query.

Ruby on Rails - Users in Groups

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.

Invite users to groups rails app

I'm building a simple rails app that allows users to login and create private lists for themselves, so far so good. I would like the user to then have the option to invite people to a certain list where these new users would have edit access to the tasks. This would be in the same vein as basecamp and trello in regards to adding users.
Where would I begin to start with this I have been wracking my brains and searching google and can't find any relevant tutorials of guidance.
Ok, so what about having
1) A users Table (model)
2) A lists table (model)
Model Associations
A user has many lists
A list belongs to a user
User table will have Foreign Key list_id (you will need to add this via a migration)
Thats just a start, I am assuming you know about resources ( the big 7 ) in rails? As you will be using this extensively
You can create a Membership table which will act as a join table between a User and List. You can then add an :admin attribute to the Membership model with a boolean type.
class List < ActiveRecord::Base
has_many :memberships
has_many :users, :through => :memberships
end
class User < ActiveRecord::Base
has_many :memberships
has_many :lists, :through => :memberships
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :list
end

Rails "Sometimes Has One" 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...

Rails -- whats the proper relationship model

I've got a rails application built for schools. The users in the system are parents who track their childrens’ activities (aka family members or just members). Teachers are also users and can log in to participate in activities. The Member model is the place that the application uses to find participants. So that teachers can be found they are added to the Member model and for the same reason, parents are added as well.
A teacher added to this application would have one record in each table user, user_member, and member. A record in user to allow him to login, 1 record in member so he can be searchable, and 1 in user_member to make the association. In this case finding a user’s own member record is trivial. But if I were a parent with a login and 2 children in the system, James and Brian, one would find 3 records in the Members table, one for James, one for Brian and one for myself. I need to know which member record is mine, not James or Brian.
What’s the best way to model this? I’ve considered two options 1) there’s a foreign key in the user table that points to a user’s own member_id OR 2) the user_members table has a boolean called ‘own_member’ which indicates this user_id’s member_id is the member record for the user. Is there one that would be preferable? One more rails like? And how would I make the call build/create the associations?
The current relationships are modeled like this:
class User < ActiveRecord::Base
has_many :user_members
has_many :members, :through => :user_members
end
class UserMember < ActiveRecord::Base
belongs_to :user
belongs_to :member
end
class Member < ActiveRecord::Base
has_many :user_members
has_many :user, :through => :user_members
end
It sounds like the UserMember join model describes which members a user has privileges to access. This is a different concept than tracking which Member record is associated to a particular user. It sounds like a user would have a member record, and a member would belong to a user implying the following database structure:
class User < ActiveRecord::Base
has_many :user_members
has_many :members, :through => :user_members
has_one :member
end
class UserMember < ActiveRecord::Base
belongs_to :user
belongs_to :member
end
class Member < ActiveRecord::Base
has_many :user_members
has_many :user, :through => :user_members
belongs_to :user
end
This means adding another database column to the members table for "user_id". Creating and building the member record from a User instance could be done as follows:
user = User.new
user.build_member
user.create_member
More info on building through associations here: http://ar.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
You might consider creating callbacks to automatically create a member record on creation of a user record so you can skip manually building the associated record. An example would be:
# app/models/user.rb
class User < ActiveRecord::Base
before_create :build_member
def build_member
self.build_member
end
end
More information on callbacks here: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Resources