# Writing to many\_to\_many table

**URL:** <https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084>\
**Category:** Rails\
**Created:** [July 4, 2006, 8:42pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084 "2006-07-04T20:42:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 4, 2006, 8:42pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/1 "2006-07-04T20:42:55Z")

</div>

I have three tables. users, posts, users\_posts. This last one is to  
mark a post as read.

How do I write to the users\_post table?

Here’s what I have:

In model ‘User\_Post’  
belongs\_to :post  
belongs\_to :user

In post/view/show:  
\<%= link\_to “Mark As Read”, :controller =\> ‘post’, :action =\>  
‘post\_read’,  
:user =\> @user.id :post =\> @post.id %\>

In post\_controller:  
def post\_read  
@postread = UserPost.new(params[:user :post])  
if @postread.save  
flash[:notice] = “Read”  
end

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 4, 2006, 8:54pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/2 "2006-07-04T20:54:16Z")

</div>

//migration file:  
create\_table :posts\_users do |t|  
t.column :user\_id, :integer  
t.column :post\_id, :integer  
end

Join tables, by default, are expected to have the tables they join in  
alpha order, hence posts\_users rather than users\_posts.

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 4, 2006, 9:39pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/3 "2006-07-04T21:39:23Z")

</div>

David C. wrote:

> //migration file:  
> create\_table :posts\_users do |t|  
> t.column :user\_id, :integer  
> t.column :post\_id, :integer  
> end
> 
> Join tables, by default, are expected to have the tables they join in  
> alpha order, hence posts\_users rather than users\_posts.

Thanks, then what?

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 4, 2006, 9:56pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/4 "2006-07-04T21:56:53Z")

</div>

comfort eagle wrote:

> David C. wrote:
> 
> > //migration file:  
> > …  
> > Join tables …  
> > Thanks, then what?  
> > I thought you asked how to write the table, but now I see you asked how  
> > to write TO the table. Sorry for answering the wrong question 🙂

DHH talked about this in his keynote at RailsConf - the idea is that you  
should think of PostUser (Posting?) as a first class citizen of your  
domain, and give it its own model and controller. In your case you may  
not need the controller, but if you give it a model you can do this in  
your PostsController (validation excluded for brevity):

def create  
@post = Post.new(params[:post])  
@post.save  
Posting.new(:user\_id =\> params[:user\_id], :post\_id =\> @post.id).save  
end

Cheers,  
David

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 5, 2006, 3:55pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/5 "2006-07-05T15:55:41Z")

</div>

David C. wrote:

> comfort eagle wrote:
> 
> > David C. wrote:
> > 
> > > //migration file:  
> > > …  
> > > Join tables …  
> > > Thanks, then what?  
> > > I thought you asked how to write the table, but now I see you asked how  
> > > to write TO the table. Sorry for answering the wrong question 🙂
> 
> DHH talked about this in his keynote at RailsConf - the idea is that you  
> should think of PostUser (Posting?) as a first class citizen of your  
> domain, and give it its own model and controller. In your case you may  
> not need the controller, but if you give it a model you can do this in  
> your PostsController (validation excluded for brevity):
> 
> def create  
> @post = Post.new(params[:post])  
> @post.save  
> Posting.new(:user\_id =\> params[:user\_id], :post\_id =\> @post.id).save  
> end
> 
> Cheers,  
> David

Instead of “Posting” I have a model for table posts\_users “PostUser”.

So substituting this: “PostUser.new(:user\_id =\> params[:user\_id],  
:post\_id =\> @post.id).save” results in error:

“blog\_development.post\_users’ doesn’t exist”.

Notice the singular “post” and multiple “users” now for the table name  
in the error msg.

Ideas?

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 5, 2006, 5:35pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/6 "2006-07-05T17:35:45Z")

</div>

> > Instead of “Posting” I have a model for table posts\_users “PostUser”.
> > 
> > So substituting this: “PostUser.new(:user\_id =\> params[:user\_id],  
> > :post\_id =\> @post.id).save” results in error:
> > 
> > “blog\_development.post\_users’ doesn’t exist”.
> > 
> > Notice the singular “post” and multiple “users” now for the table name  
> > in the error msg.

rename to postings and Posting 🙂

> The posts\_users name is only relevant if you want the automagic of  
> has\_and\_belongs\_to\_many. If you don’t, and you have a first class join  
> model to link posts and users, I’d give it a better name.

I do want the magic though.

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 5, 2006, 5:17pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/7 "2006-07-05T17:17:28Z")

</div>

comfort eagle wrote:

> Instead of “Posting” I have a model for table posts\_users “PostUser”.
> 
> So substituting this: “PostUser.new(:user\_id =\> params[:user\_id],  
> :post\_id =\> @post.id).save” results in error:
> 
> “blog\_development.post\_users’ doesn’t exist”.
> 
> Notice the singular “post” and multiple “users” now for the table name  
> in the error msg.
> 
> Ideas?

Yup, rename to postings and Posting 🙂

The posts\_users name is only relevant if you want the automagic of  
has\_and\_belongs\_to\_many. If you don’t, and you have a first class join  
model to link posts and users, I’d give it a better name.

Alan

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 5, 2006, 9:57pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/8 "2006-07-05T21:57:25Z")

</div>

You won’t get “the magic” because it’s not that kind of a join. If all  
you  
wanted was to map a user to a post, you could use “the magic” of  
has\_and\_belongs\_to\_many. Since you want to store additional information  
on  
that linking table, you need to make that linking table a new model.  
Then  
you use has\_many :through to make it work the way you want.

Here’s kinda what you want.

class Readings\< ActiveRecord::Base  
belongs\_to :post  
belongs\_to :user  
end  
class Post\< ActiveRecord::Base  
has\_many :readings, :dependent =\> :destroy  
has\_many :users, :through =\> :readgins  
end  
class User\< ActiveRecord::Base  
has\_many :readings, :dependent =\> :destroy  
has\_many :posts, :through =\> :readings  
end

See this for some insight:

[http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off](http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off)

---

<div class="post-metadata">

**Author:** ![comforteagle](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/dfb087/32.png) [@comforteagle](https://www.ruby-forum.com/u/comforteagle)\
**Post date:** [July 6, 2006, 7:15pm UTC](https://www.ruby-forum.com/t/writing-to-many-to-many-table/97084/9 "2006-07-06T19:15:04Z")

</div>

“@postread = PostUser.new(:user\_id =\> params[:user\_id], :post\_id =\>  
params[:post\_id]).save” ended up working in my action.

Maybe I’ll have more trouble getting that info out in a meaningful  
manner though.
