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.
If you don't need to do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship (though you'll need to remember to create the joining table in the database). You should use has_many :through if you need validations, callbacks, or extra attributes on the join model.
The difference between belongs_to and has_one is a semantic one. The model that declares belongs_to includes a column containing the foreign key of the other. The model that declares has_one has its foreign key referenced.
has_one means that there is a foreign key in another table that references this class. So has_one can ONLY go in a class that is referenced by a column in another table. For a two-way association, you need one of each, and they have to go in the right class. Even for a one-way association, it matters which one you use.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With