Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails multiple belongs_to assignment

Given

User:

class User < ActiveRecord::Base
   has_many :discussions
   has_many :posts
end

Discussions:

class Discussion < ActiveRecord::Base
    belongs_to :user
    has_many :posts
end

Posts:

class Post < ActiveRecord::Base
    belongs_to :user
    belongs_to :discussion 
end

I am currently initializing Posts in the controller via

@post = current_user.posts.build(params[:post])

My question is, how do I set/save/edit the @post model such that the relationship between the post and the discussion is also set?

like image 680
James Pleasant Avatar asked Jul 18 '12 10:07

James Pleasant


1 Answers

Save and edit discussions along with post

Existing Discussion

To associate the post you're building with an existing discussion, just merge the id into the post params

@post = current_user.posts.build(
          params[:post].merge(
            :discussion_id => existing_discussion.id
        ) 

You will have to have a hidden input for discussion id in the form for @post so the association gets saved.


New Discussion

If you want to build a new discussion along with every post and manage its attributes via the form, use accepts_nested_attributes

class Post < ActiveRecord::Base
  belongs_to :user
  belongs_to :discussion
  accepts_nested_attributes_for :discussion
end

You then have to build the discussion in the controller with build_discussion after you built the post

@post.build_discussion

And in your form, you can include nested fields for discussions

form_for @post do |f|
  f.fields_for :discussion do |df|
    ...etc


This will create a discussion along with the post. For more on nested attributes, watch this excellent railscast


Better Relations

Furthermore, you can use the :through option of the has_many association for a more consistent relational setup:

class User < ActiveRecord::Base
  has_many :posts
  has_many :discussions, :through => :posts, :source => :discussion
end

class Discussion < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
  belongs_to :discussion 
end

Like this, the relation of the user to the discussion is maintained only in the Post model, and not in two places.

like image 199
Beat Richartz Avatar answered Oct 07 '22 23:10

Beat Richartz