I have these models:
class Profile
has_many :projects, :through => "teams"
has_many :teams, :foreign_key => "member_id"
has_many :own_projects, :class_name => "Project", :foreign_key => :profile_id
has_many :own_teams, :through => :own_projects, :source => :teams
end
class Project
belongs_to :profile, :class_name => "Profile"
has_many :teams
has_many :members, :class_name => "Profile", :through => "teams", :foreign_key => "member_id"
end
class Team
belongs_to :member, :class_name => 'Profile'
belongs_to :project
end
I want to create model Evaluation. It will need the ID of the Project Owner, the ID of a Member of this Project, and the ID of the Project. Explaining better, The Owner of the Project will Evaluate all his members, one by one. And the members will evaluate just the owner of the project. The table Evaluation will have a lot of attributes plus those Ids mentioned before.
My question is: How would my models be to make it function with evaluation, and how would be model evaluation itself? has_and_belongs_to_many or has_many :through?
Thanks.
Edited
Shot in the dark
class Evaluations < ActiveRecord::Base
belongs_to :evaluated, :class_name => 'Profile', :foreign_key => "evaluated_id"
belongs_to: :evaluator, :class_name => 'Profile', :foreign_key => "profile_id"
end
Guess I won't need the ID from Project...
Project owner evaluates member performance for a project
Members will evaluate the project owner for his performance on a project
So, Evaluation has an evaluator, evaluee, a project, and other attributes
We also need to know the types of the evaluee and evaluator
Create 2 evaluation classes one for EmployeeEvaluation, one for ManagerEvaluation. Use Single table inheritance.
class Evaluation < ActiveRecord::Base
attr_accessible :evaluator, :evaluee
belongs_to :project
end
class EmployeeEvaluation < Evaluation #project manager evaluation of employee
def evaluator
Manager.find(self.evaluator)
end
def evaluee
Employee.find(self.evaluee)
end
end
class ManagerEvaluation < Evaluation
def evaluator
Employee.find(self.evaluator)
end
def evaluee
Manager.find(self.evaluee)
end
end
Related
I have a User model, a Listing model and an Order model. A user can either place an order or publish a listing which others can place an order for. Thus, a User can be customer as well as supplier.
My Order model has listing_id, from_id and to_id.
My question is, how can I set up associations between these models ? I read the rails guide on associations but the example there were dealing with separate customer and supplier models.
class User < ActiveRecord::Base
has_many :listings, :foreign_key => :supplier_id, :inverse_of => :supplier
has_many :orders, :foreign_key => :customer_id, :inverse_of => :customer
end
class Listing < ActiveRecord::Base
belongs_to :supplier, :class_name => 'User'
belongs_to :order
end
class Order < ActiveRecord::Base
belongs_to :customer, :class_name => 'User'
has_many :listings
end
I have users and projects. User can have many projects and project can have many users. Now project has a particular user as an author or the creator, ie. project has one creator and that creator is also a user. How do I map this relation in rails !!!
#Project
has_and_belongs_to_many :users
belongs_to :author, :class_name => "User"
#User
has_and_belongs_to_many :projects
has_many :authored_projects, :class_name => "Project", :foreign_key => "author_id"
And you need to add author_id to the projects table.
So you can use: project.author, user.authored_projects, etc
Try this
class User < ActiveRecord::Base
has_and_belongs_to_many :projects
has_many :created_projects, :class_name => "Project", :foreign_key => "creator_id"
end
class Project< ActiveRecord::Base
has_and_belongs_to_many :users
belongs_to :creator, :class_name => "User"
end
I have a User model which has many projects and a Project model which can have many users, but also belongs to a single user (ie the user who created this project). It must belong to a User. It also allows a list of users to be associated with it, think collaboration.
With this in mind, my models look like this:
class User < ActiveRecord::Base
has_many :assigned_projects
has_many :projects, :through => :assigned_projects
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :assigned_projects
has_many :users, :through => :assigned_projects
end
class AssignedProject < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
Now, when I want to create a new project through a User, this is how I would do it:
user = User.create(:name => 'injekt')
user.projects.create(:name => 'project one')
Now, I know that projects is provided through an AssignedProject join model, which is why project.user will return nil. What I'm struggling to get my head around is the best way to assign the project creator (which by the way doesn't need to be user, it could be creator or something else descriptive, as long as it is of type User).
The idea then is to create a method to return projects_created from a User which will select only projects created by this user. Where user.projects will of course return ALL projects a user is associated with.
Assuming this kind of association is fairly common, what's the best way to achieve what I want? Any direction is greatly appreciated.
Add a creator_id column to your projects table for the creator relationship, and then add the associations to the models:
class User < ActiveRecord::Base
has_many :assigned_projects
has_many :projects, :through => :assigned_projects
has_many :created_projects, :class_name => "Project", :foreign_key => :creator_id
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :assigned_projects
has_many :users, :through => :assigned_projects
belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
end
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
I wanted to add little improvement to design. We don't actually need intermediate model because it does not contain any extra column other than reference_ids hence HABTM association is best suited over here.
class User < ActiveRecord::Base
has_and_belongs_to_many :projects, :join_table => :assigned_projects
has_many :created_projects, :class_name => "Project", :foreign_key => :creator_id
end
class Project < ActiveRecord::Base
has_and_belongs_to_many :users, :join_table => :assigned_projects
belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
end
class Profile
has_many :projects, :through => "teamss"
has_many :teams, :foreign_key => "member_id"
has_many :own_projects, :class_name => "Project", :foreign_key => :profile_id
has_many :own_teams, :through => :own_projects, :source => :teams
end
class Project
belongs_to :profile, :class_name => "Profile"
has_many :teams
has_many :members, :class_name => "Profile", :through => "teams", :foreign_key => "member_id"
end
class Team
belongs_to :member, :class_name => 'Profile'
belongs_to :project
end
I need to create model Evaluation. What I want to do is generate a link in project#view page for each member of the project, including the owner, in order to make an Evaluation The person will click on the link and evaluate the person related to this link. The owner of the Project will evaluate all the members, and all the members will evaluate the owner.
I have defined model Evaluation as following, but I think I miss something:
class Evaluations < ActiveRecord::Base
belongs_to :evaluated, :class_name => 'Profile', :foreign_key => "evaluated_id"
belongs_to: :profile, :class_name => 'Profile', :foreign_key => "profile_id"
end
Remembering that Evaluation table will have tons of attributes, that's why I'm going not going with has_many_and_belongs_to_many.
How can I create this model in order to do what I want and be able to acess all I need via project#show page?
Thanks!
Edited
Changes done:
class Profile
has_many :evaluations, :dependent => :destroy, :foreign_key => :evaluation_id
has_many :evaluators, :through => :evaluations, :foreign_key => :profile_id
end
class Project
has_many :evaluations,:foreign_key => "project_id"
end
class Evaluations < ActiveRecord::Base
belongs_to :evaluated, :class_name => 'Profile', :foreign_key => "evaluated_id"
belongs_to: :profile, :class_name => 'Profile', :foreign_key => "profile_id"
belongs_to: :project, :class_name => 'Project', :foreign_key => "project_id"
end
You have your team and profile (member) associations a little messed up. A team has many profiles (members), and a profile (member) belongs to a team. Beyond that, you may just be over-complicating things. I'm curious as to why you wouldn't just call the Profile Model Member instead and keep things that much simpler?
That being said, you are doing a pretty complex set of associations. I would highly recommend you read the ActiveRecord Associations doc closely to get a firm understanding of how these things work, especially how primary and foreign keys are automagically determined.
I think below will get you what you want.
class Team
has_and_belongs_to_many :members,
:class_name => "Profile"
belongs_to :project
belongs_to :team_leader,
:class_name => "Profile"
end
class Profile
has_and_belongs_to_many :teams
has_many :projects,
:through => :teams
has_many :owned_projects,
:class_name => "Project",
:foreign_key => "owner_id"
has_many :owned_teams,
:class_name => "Team",
:foreign_key => "team_leader_id"
has_many :evaluations
has_many :evaluations_given,
:class_name => "Evaluation",
:foreign_key => "evaluator_id"
end
class Project
has_many :teams
belongs_to :owner,
:class_name => "Profile"
has_many :members,
:through => :teams
has_many :evaluations
end
class Evaluation
belongs_to :profile
belongs_to :evaluator,
:class_name => "Profile",
:foreign_key => "evaluator_id"
belongs_to :project
end
In support of these model definitions would be the following tables/keys:
evaluation
id
profile_id
evaluator_id
project_id
teams
id
project_id
team_leader_id
profiles
id
project
id
owner_id
profiles_teams
profile_id
team_id
With this, you should be able to access collections/objects that you need to get your links right such as:
project.members
project.owner
project.teams
team.project
profile.projects
profile.owned_projects
profile.teams
team.members
team.leader
project.evaluations
profile.evaluations
evaluation.evaluator
profile.evaluations_given
Note, also, that your nested resources are going to be just as complex, if you try to stay with a RESTFUL framework. Read up!
I've got a Project model, and a Contact model. The Project model has an owner and a client, both of which are Contacts. I've obviously got something ambiguous going on, because if I have a contact and ask for its projects, Rails won't know whether I'm asking for it's projects where it's the client or where it's the owner. So far I've got this:
class Contact < ActiveRecord::Base
has_many :projects
end
class Project < ActiveRecord::Base
belongs_to :owner, :class_name => 'Contact', :foreign_key => 'owner_id'
belongs_to :client, :class_name => 'Contact', :foreign_key => 'client_id'
end
How do I make two relationships here?
Its similar to the way belongs_to is defined in the other class.
So Basically
class Contact < ActiveRecord::Base
has_many :projects_owned, :class_name => "Project", :foreign_key => "owner_id"
has_many :projects_as_client, :class_name => "Project", :foreign_key => "client_id"
end
names of associations could be better. The Single Table inheritance approach described before me is also a neat way, but go for it if you have a lot of different behaviour for each of the OwnerContact and ClientContact class, otherwise it might be just a useless overhead.
I think here's should be polymorphic association, something like this
class Owner < ActiveRecord::Base
has_many :projects, :as => :person
end
class Client < ActiveRecord::Base
has_many :projects, :as => :person
end
class Project < ActiveRecord::Base
belongs_to :person, :polymorphic => true
end
Now you can retrieve projects by #client.projects or #owner.projects. If you want to get person from #project you should add to Project migration this:
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.references :person, :polymorphic => true
t.timestamps
end
end
...
You should try to use a single table inheritance on the Contact table. All you need to do for this to work is to implement a 'type' column (string). Rails will handle the rest
class Contact < ActiveRecord::Base
# implement a type column
has_many :projects
end
class OwnerContact < Contact
end
class ClientContact < Contact
end
class Project < ActiveRecord::Base
belongs_to :owner, :class_name => 'OwnerContact'
belongs_to :client, :class_name => 'ClientContact'
end