I am creating an app that deals with sports teams. Currently I have two models. A Users.rb model and a Teams.rb model. Within the users of the app I would like to have team captains and teammates. I would like to give the captain the privledge of creating the team when they sign up. I would like the a captain to belong to a team and teammates belong to a team. I would like the team to just have one captain. What would the best way to set this up? Should I have a captain and a teammate alias in the users model? Or would it be better to make a captains.rb model?
Ok, First lets lay out the relationship assumptions since there are some that are vague from your descriptions:
A user can:
Be many captains
Be on many teams
A team can:
Belong to one captain
Have many users as teammates
From this I think you need 3 models:
User
Team
Teammates that acts as the has_many_through join table between users and teams
The Teammate model would definitely have:
user_id
team_id
Possible role/type field
And this leaves the point where you have to make a decision about the app based on how you will use the data. Since a team will only have one captain you could leave out the role field in the teammate model and just add a user_id or captain_id to the actual Team model. This would mean captain is treated as special and different from the other team mates always. However, I'm guessing for somethings you could want to loop through all members of the team including the captain. That's why you should probably just make captain a special role on the teammate model and add validation to make sure there is only one captain. Then you don't have to do special handling for the captain whenever looping through the entire team.
Assuming you go with the role field then your final models would have the following relations:
Teammate
belongs_to :team
belongs_to :user
User
has_many :teammates
has_many :teams, through: :teammates
Team
has_many :teammates
has_many :users, through: :teammates
has_one :team_captain, -> { where role: 'captain' }, class_name: 'Teammate'
You could also get fancier with that last one by working out a has_many through to get to the captain user instead of the captain team_mate. This post has some interesting details on advanced has_one:
http://www.rojotek.com/blog/2014/05/16/cool-stuff-you-can-do-with-rails-has_one/
If the captains and teammates have different attributes so i think its better to separate the models but if this is not the case so why do not you create a join table for teammates between users and team and the team model has an owner id.
Schema example :
Team ( owner_id, .....)
Teammates( user_id, team_id, .... )
This will help you to set a belongs_to association between Team and User models as Captain using the owner_id column in the team model and the other members can be done by has_many teammates through Teammates Model or even use has_and_belongs_to_many association.
By this way you will manage to let one user has_one team or even a teammate within other teams.
Another idea to let all the members within the join table with an extra Column to decide its role within the team ,which will give you more control if you are going to add more roles in the future, and define your validations and scoops to serve that way.
I'd do as follow:
At the beginning app allows you to signup as "user aka team owner" or as "teammate"
Users.rb - can create teams and invite other teammates. Has administrative rights.
Teams.rb - belongs to User and has many Teammates.
Teammates.rb - belongs to Teams.
All assigned teammates could have admin-visible checkbox "captain" with boolean value. This could save you from creating one more db table. Unless "captain" is "true", teammate status is "simple player". Otherwise it's "captain".
Other way is to allow Users to create Teams and Teammates.
User would has_many Teams and Teammates.
Teammate belongs_to User and belongs_to the Team.
Team belongs_to User and has_many Teammates.
Related
I need advice/help in implementing the design of my models in a university HR web application that I'm currently developing.
First, I have these models for my tables with their fields:
Students
* different fields
Faculty
* different fields
Users
* username
* password_digest
I have Students and Faculty objects for CRUD that have their unique fields/attributes in their own tables. At the same time, I see these objects as the types of Users that uses the app.
I'm confused on how to model them properly, experimenting either with ActiveRecord's STI or Polymorphism techniques. All I want the app to do is to recognize the type of User that is signing in and then display or redirect to the appropriate page for that type of User. At the same time have reference to its associated record in the Faculty or Student table.
What is best way to approach this assuming I have these conditions:
Users can either be a Student, Faculty, or Admin. Later on I can add/model non-faculty members to the applicaton as well.
Student/Faculty can opt to have or not have an associated User account. (Some students and faculty members don't want to use the app)
Admin users have access to the administrative (CRUD) side of the app. Student and Faculty can only handle their own records.
I might be wrong, but my bet is to go polymorphic and put the reference in the User model:
class User < ActiveRecord::Base
belongs_to :userable, polymorphic: true
end
class Student < ActiveRecord::Base
has_one :user, as: :userable
end
class Faculty < ActiveRecord::Base
has_one :user, as: :userable
end
P.S.: I don't know if the "userable" term sounds right, just correct me if there's a better way to name it.
One Simple method is, So you can easily manage with common fields as well
# User should have a type field (string)
class User < ActiveRecord::Base
end
class Student < User
end
class Faculty < User
end
This spells out very clearly the way you need to go:
"Student/Faculty can opt to have or not have an associated User account. (Some students and faculty members don't want to use the app)"
This means that Student, Faculty and User need to be completely different things: you need to be able to have a Faculty account which doesn't have a user account. So, your polymorphic approach is the right way to go i think.
BTW, i would rename Faculty, since Faculty has a different meaning: a faculty is a department or division within the university, it's not a person. Later on in your app's development you may need to associate classes, students or staff members with a Faculty and then it's going to get confusing. I would use FacultyMember since that's how staff are usually described.
"userable" is an awkward word to use for the relationship. What about "scholar"? That can describe both staff and students, and it conveys the idea that it's referring to an actual person, as opposed to "user" which is really a user account rather than a person.
Please forgive me if this has been answered already but I've searched a lot and still require some clarification.
I'm building a Property Management tool using Rails 3.2. I already have a User model and authorisation/authentication code in place with full tests coverage.
I've just started drawing out the models/classes/tables and have gotten myself a bit confused.
Let's start with Users.
Modelling Users
I plan to have allow multiple companies to use this system. Each will have employees (users). These users will have different roles e.g. Manager, Agent, Accountant, Secretary etc. For the most part the data I plan to store for each of these users will be similar (or so I think at the moment) so I am leaning towards Single Table Inheritance and using the type to define the level of access each employee has.
Secondly, I plan to allow Landlord and Tenants to also log in to the system. Upon logging in they'll be able to view information about the property they are owning or renting - maybe keep their contact details up to date too.
I was thinking of using polymorphic associations to represent these users.
So the plan I have at the moment and would like some feedback on is to have
User < ActiveRecord::BASE
Employee < User (this will have a STI type column and allow for the different employee roles)
Landlord < User
Tenant < User
Is this the best way of approaching this problem or am I shooting myself in the foot?
I've had some people advise me I should have a 'roles' table and assign roles to the users - but I have a feeling this isn't the most elegant way to do this in Rails.
Properties
My next issue is with Properties. Right now I have a model for properties and when I add them they belong_to a User (i.e. they have a user_id foreign key). I then started thinking "what happens if the employee (user) that added the Property leaves the company or has their account deleted for some reason?"
So in this scenario is it best to forgo the User/Employee to Property association and just link the Property to the Company that the employee belongs to? This way I can all employee.company.properties to list out all the properties?
Landlord and Tenant associations
Let's presume we make Properties belong to a Company.
In terms of associations this is what I have in my head. Looking at it now I see that everything belongs to a company because one company using the system shouldn't be able to see the landlords/tenants/employees/properties of another company.
class Landlord < User
belongs_to :company
has_many :properties, :through => :ownerships
end
class Tenant < User
belongs_to :company
has_one :property, :through => tenancies #you can only live at one place at a time right?
end
class Property < ActiveRecord::Base
has_many :tenants, :through => :tenancies
has_many :landlords, :through => :ownerships
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :properties
has_many :employees
has_many :landlords :through => :ownerships #not sure if through is required/works here
has_many :tenants :through => :tenancies #not sure if through is required/works here
end
class Employees < User
belongs_to :company
end
Properties
Also I'm guessing we'll have different types of Properties (Commercial/Residential) and of those there will be whole buildings, apartments within a building (single address) etc.
Like with users I'm planning on using Polymorphic Associations to define two subclasses CommercialProperty and ResidentialProperty and then use sti to define a type. If the type is "multi unit" then have a new model for units and an association whereby Property has_many Units and a Unit belongs_to a property.
Aim
I'm trying to make sure that my code follows best practice as much as possible so that when I come to add new features and expand I'm not left having to re-write large chunks of the app.
I would really appreciate your feedback.
Reference
Some of the posts I've read. Hopefully to help others trying to solve the same problem.
Designing a Rails application: single table inheritance?
Ruby on rails with different user types
Ruby On Rails User Model for multiple types
It's probably too late but you could also use has_and_belongs_to_many on User and Company and thus avoid STI altogether by using gems cancan and rolify.
It allows you to define finely grained access rights (abilities).
I know that it seems more elegant having different classes instead of roles, but it is not viable long-term strategy, it can become messy when logic becomes complex.
Other then that, the rest seems pretty solid, hope that helps :)
I've been thinking about this for a while now, and though it seems simple enough i can't really seem to get it "right".
What i have, basically, is two classes, Companies and Employees. It is set up so that a Company has_many Employees, and Employees belong_to a Company. Also i use STI, so i have that Company < User and Employee < User. All that is good enough. Now, Employees can only do two things: See their own profile and update it. Companies on the other hand can create employees. In the application this is the only way to create employees. My problem is that i wanna make this as simple as possible, also thinking about that i might make an API at some point. So my question is what is considered good practice here? Should i make Employees a nested resource under Companies? Should i create a Employees resource under a Companies namespace? Should i just keep all actions in the employees_controller and then use permissions to allow companies to acces them? It seems that everything i try ends up feeling "not right".
From what you are asking, there seems to be 2 types of users: The normal user, which is not employee and the employee. Rails has a belongs_to and has_many relationship between models. So for the company you can do:
class Company < ActiveRecord::Base
has_many :users, :dependent => :destroy
class User < ActiveRecord::Base
attr_accessible :is_employee
belongs_to : company
In the User model, there is a column name is_employee which stores boolean values. That way, you can have both the employee and non-employee. In the Company, if Company is destroyed, its Users will be gone.
More documentation about those relationship can be found here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
I've been watching Ryan's screencast:
http://railscasts.com/episodes/196-nested-model-form-part-1
I have a similar but different problem, and am hoping someone can help.
I have the following four models that are required (at minimum) to register:
Account
Company
Address
User
At registration, I'd like for Company, Address, and User to individually be associated with Account directly.
Also, I would like te User to be associate with the Company, and the Address to be associated with the Company.
Note: Each has a foreign key: account_id -- This is essentially a multi-tenant system with a single database.
My associates are currently setup as follows:
Account
has_many :companies
has_many :users
has_many :addresses
(In the future, other models will use the Company and the Address model, that is why Account has many of those)
User
belongs_to :account
belongs_to :company
Company
belongs_to :account
has_many :users
has_many :addresses
Address
belongs_to :account
belongs_to :company
I've been using accepts_nested_attributes_for method in the models, and the fields_for method in the views, but have only been able to get things associated in a purely nested way.
In other words, a User gets associate to a Company, but is not associated to an Account.
I need for each of the models to be associated with the Account. (Except for Account itself of course)
Is there a way to do this?
Thank you.
I think you confuse some where.
Account Has Many Companies
Company Has Many Users
Company belongs to account
account User belongs_to company
user belongs_to account either through company or create account_id in user
In views you can create form company and then create fields_for for account and inside account create fields_for user.
I think this will solve your purpose.
don't forget to add accept_nesetd_attributes inside company and account
I have a User and Project model. A user can have multiple projects, and a project can have multiple users. This of course is simple with a has_and_belongs_to_many association. My problem is that I'd also like to track the user who created the project. This would be simple with a belongs_to :user for my Project model. The problem then is that doing a has_many :projects for a User when a user already has a HABTM relationship with a Project makes little sense.
Here's what I would eventually like to achieve:
# building a project with the currently logged in user
current_user.projects.build(...)
# now when a user wants to add another user to this project
project = current_user.projects.find(...)
project.users << User.find(...)
# grabbing information
some_project.user #=> The user who created this project
some_project.users #=> The array of User objects associated
some_user.projects #=> The array of Project objects associated
In the future it's likely a User will have the same sort of relationship with a Group, where a User would both have many and belong to many groups. But again I would also like to track the creator of this Group.
It's quite likely I'm missing something. What's a common way to achieve this?
If it helps to clarify, a possible configuration is laid out below:
Group
has_and_belongs_to_many :users
belongs_to :user
has_many :projects
Only a User should have the ability to create a Group
User
has_and_belongs_to_many :groups
has_many :projects
Can great a group or a project, and can also belong to both
Project
has_and_belongs_to_many :users
belongs_to :group
both a User and a Group should have the ability to create a Project
I've also tried doing simple has_and_belongs_to_many for each association and including a creator_id for example, and tracking this myself. For example.. Project.create(:creator_id => current_user.id) but this seemed hackish and I was sure they would be a better way to do this. Apologies for my ignorance if I've missing something simple.
Reading this again you want to have one owner of the project, either a group or a user. Store that as a polymorphic belongs_to relationship from the project model. ie. owner_type => 'User'/'Group' owner_id => 123
Other users associated with the group are many to many so you need a join table.
Your group model is a separate model with a many to many relationship with users so you can simply store the user who created it as a field of the group model ie. :user_id 123.