Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails has many and belongs to one

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.

like image 348
Lee Jarvis Avatar asked Jun 30 '11 14:06

Lee Jarvis


People also ask

When to use has and belongs to many?

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.

Has one vs belongs to Rails?

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.

Does Rails have one Ruby?

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.


2 Answers

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

like image 67
Pavling Avatar answered Oct 14 '22 20:10

Pavling


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
like image 21
Sandip Ransing Avatar answered Oct 14 '22 18:10

Sandip Ransing