# Associations (belongs\_to, has\_one, and has\_many) questions

**URL:** <https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881>\
**Category:** Rails\
**Created:** [August 3, 2008, 9:36pm UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881 "2008-08-03T21:36:19Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 3, 2008, 9:36pm UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/1 "2008-08-03T21:36:19Z")

</div>

Greetings,

This is something that has completely stumped my development processes  
on my new application. The application helps members exchange feedback  
on their stories (for creative writers). With that in mind, I’m trying  
to create associations between the different tables:

class Member \< ActiveRecord::Base  
has\_many :stories  
has\_many :critiques  
end

class Story \< ActiveRecord::Base  
has\_many :critiques  
belongs\_to :member # foreign key =\> member\_id  
end

class Critique \< ActiveRecord::Base  
belongs\_to :story # foreign key =\> story\_id  
belongs\_to :member # foreign key =\> member\_id  
end

I’m not entirely sure, though I’m under the impression that as long as  
you set up the associations correct and add the correct columns  
(foreign keys), Rails will use its magic. For example, if I create a  
new story, then the member\_id column would automatically be updated  
with the active member’s id. Unfortunately, this doesn’t happen in my  
application. Thus, I’m either doing something wrong (very possible),  
or Rails doesn’t do this automatically.

Is the above code correct? If so, does Rails populate the foreign key  
column automatically? If so… what am I doing wrong?

My next question has to deal with what you can do with these  
associations. Lets say I wanted to display within my index.html.erb  
file a list of stories (links) and for each story, a link to each of  
their critiques. How would the code in my controller look? And how  
would I structure my view code?

I’ve read over a lot of the API documentation, the rails way, the  
agile development book, and many posts here. It’s just not clicking.  
So, any help would be very much appreciated. Thank you for your time  
and assistance!

~Dustin T.

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 3, 2008, 9:42pm UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/2 "2008-08-03T21:42:45Z")

</div>

On 3 Aug 2008, at 20:35, Dustin T. wrote:

> has\_many :critiques  
> end
> 
> I’m not entirely sure, though I’m under the impression that as long as  
> you set up the associations correct and add the correct columns  
> (foreign keys), Rails will use its magic. For example, if I create a  
> new story, then the member\_id column would automatically be updated  
> with the active member’s id. Unfortunately, this doesn’t happen in my  
> application. Thus, I’m either doing something wrong (very possible),  
> or Rails doesn’t do this automatically.

> Is the above code correct? If so, does Rails populate the foreign key  
> column automatically? If so… what am I doing wrong?

Depends what you mean. If you just do Story.create then member\_id  
won’t be set.  
if you do current\_user.stories.create then it will be set to  
current\_user.id

> My next question has to deal with what you can do with these  
> associations. Lets say I wanted to display within my index.html.erb  
> file a list of stories (links) and for each story, a link to each of  
> their critiques. How would the code in my controller look? And how  
> would I structure my view code?

well you’d fetch some stories, and probably stick them in @stories.  
Then you’d just iterate over @stories, and for each stories iterate  
over @stories.critiques (I use iterate in a loose sense - you could  
just as easily be rendering a partial.

Fred

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 3, 2008, 11:08pm UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/3 "2008-08-03T23:08:13Z")

</div>

Thanks Frederick for the quick reply!

Unfortunately, I’m still very new to Rails and am unsure how to use  
your advice. My application is setup utilizing the basic scaffolding,  
which I’ve changed a lot. Thus, my create method looks like:

def create  
@story = Story.new(params[:story])

if @story.save  
flash[:notice] = ‘Story was successfully created.’  
redirect\_to manage\_stories\_path  
else  
render :action =\> “new”  
end  
end

I commented everything out and tried to use:  
current\_user.stories.create, though Rails doesn’t understand what  
‘current\_user’ is. Thus, I thought perhaps you meant ‘current\_member’  
as I don’t have a user class. I tried that with no success. Finally, I  
simply tried: member.stories.create, which also doesn’t work (is not  
understood by Rails).

If it’s not too much to ask, perhaps a working example of the create  
method? Right now the method looks like: (note, there is nothing  
checking whether or not the save was successful. I can add that back  
in once I understand your original suggestion).

def create  
current\_member.stories.create(params[:story])  
redirect\_to manage\_stories\_path  
end

As for my second question, here is an example of what I am currently  
doing within my controller to find the content:

def show  
@story = Story.find(params[:id])  
@critique = Critique.find(:all, :conditions =\> [‘story\_id = ?’,  
@story.id])  
@member = Member.find(:first, :conditions =\> [‘id = ?’,  
@story.member\_id])  
end

I’m used to doing everything manually (coming from PHP), though read  
that there is a better way to do the above through associations. I  
just can’t seem to get anything else to work. Concerning the view, I  
believe I understand what you mean and will give it a go once I have  
the controller figured out.

I apologize for being so inexperienced here. This is one thing that  
I’m really struggling with. Thank you again for your time and help on  
this!

~Dustin T.

On Aug 3, 1:41 pm, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 4, 2008, 1:13am UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/4 "2008-08-04T01:13:21Z")

</div>

Hello Frederick,

Thank you very much. When I was waiting for a reply, I kept playing  
with the code and found a different part of the API documentation that  
I had missed. I was able to get the content to come up correctly (by  
mere chance) - very exciting. :o)

Your explanation above really solidified my short learning experience.  
I see now that I don’t need all those extra instance variables, as I  
can do something like:

\<% for critique in story.critiques -%\>  
…  
\<% end -%\>

> I was assuming that you already had a function to return the  
> current\_user or member. Normally whatever you use to manage logging in  
> to your app will provide this.

I see. That makes more sense now. My log in / out is based off the  
Agile Web D. with Rails 3rd Edition (still in beta). I’ll  
have to play around with this and see how I can make it work.

Thank you again for all your assistance. My progress is moving  
smoothly forward once again. :o)

~Dustin T.

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 4, 2008, 12:01am UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/5 "2008-08-04T00:01:27Z")

</div>

On 3 Aug 2008, at 22:07, Dustin T. wrote:

> if @story.save  
> flash[:notice] = ‘Story was successfully created.’  
> redirect\_to manage\_stories\_path  
> else  
> render :action =\> “new”  
> end  
> end
> 
> I commented everything out and tried to use:  
> current\_user.stories.create, though Rails doesn’t understand what  
> ‘current\_user’ is. Thus, I thought perhaps you meant ‘current\_member’

I was assuming that you already had a function to return the  
current\_user or member. Normally whatever you use to manage logging in  
to your app will provide this.

> def show  
> @story = Story.find(params[:id])  
> @critique = Critique.find(:all, :conditions =\> [‘story\_id = ?’,  
> @story.id])  
> @member = Member.find(:first, :conditions =\> [‘id = ?’,  
> @story.member\_id])  
> end

What you’ve got is the same as  
@story = Story.find(params[:id])  
@critiques = @story.critiques  
@member = @story.member

I probably wouldn’t bother with @critiques and @member in this case.

In your view you’d probably do something like

\<%= render :partial =\> ‘critique’, :collection =\> @story.critiques %\>  
You should have a \_critique.html.erb file which contains the markup  
for a single critique (when that partial is rendered the current  
critique will be available as critique)

Fred

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 4, 2008, 6:31am UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/6 "2008-08-04T06:31:58Z")

</div>

Greetings - again!

I’ve hit that wall again and hope this is a quick and easy problem to  
solve. When I’m within my view code, something like:  
story.member.username, would work just fine. However, within my  
controller, it doesn’t seem to recognize what member or critiques are.  
Thus, the following code doesn’t work:

> What you’ve got is the same as  
> @story = Story.find(params[:id])  
> @critiques = @story.critiques  
> @member = @story.member

Furthermore, I would like to find the name of the member who posted  
feedback. I have the following code, though it doesn’t work:

\<% for story in @stories -%\>  
\<% for critique in story.critiques -%\>  
\<%= critique.member.username %\>  
\<% end -%\>  
\<% end -%\>

The member class has\_many critiques and critiques belongs\_to the  
member class. Just as I would be able to do: story.member.username, I  
thought I would be able to do story.critique.member.username. It seems  
that I am wrong. \>\<

Finally, I was able to get  
current\_user.critiques.create(params[:critique]) to work. I created a  
new method within the application.rb and it successfully assigns my  
foreign key. However, it only does so for the member\_id foreign key,  
and not the story\_id. After a long while of trying to get both to be  
set, I surrendered and did the following:

@critique = Critique.new(params[:critique])  
@critique.story\_id = @story.id  
@critique.member\_id = current\_user

Is this ‘okay’ code, or should I be doing something else?

Sorry to keep bothering you guys (mainly Frederick), I just can’t seem  
to find answers anywhere on this particular subject. I truly try not  
to post questions as figuring something out has the added bonus of  
learning more and remembering the content. If you know of any specific  
article, tutorial, or section in a book, peepcode, or anything that I  
should study up on, please let me know (I have all of them…).

Thanks for your help!

~Dustin T.

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 4, 2008, 3:07pm UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/7 "2008-08-04T15:07:15Z")

</div>

Hi,  
check the variables calls :

> > What you’ve got is the same as  
> > @story = Story.find(params[:id])  
> > @critiques = @story.critiques  
> > @member = @story.member
> 
> Furthermore, I would like to find the name of the member who posted  
> feedback. I have the following code, though it doesn’t work:
> 
> \<% for story in @stories -%\>  
> @stories should be declared in your controller : note that it should  
> be an Array (probably resulting from a find), otherwise the plural is  
> not relevant.  
> \<% for critique in story.critiques -%\>  
> \<%= critique.member.username %\>  
> \<% end -%\>  
> \<% end -%\>

* * *

Mathieu BODIN

---

<div class="post-metadata">

**Author:** ![tinney](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/a88e4f/32.png) [@tinney](https://www.ruby-forum.com/u/tinney)\
**Post date:** [August 4, 2008, 5:05pm UTC](https://www.ruby-forum.com/t/associations-belongs-to-has-one-and-has-many-questions/144881/8 "2008-08-04T17:05:44Z")

</div>

Thanks Tongman for your reply.

> @stories should be declared in your controller : note that it should  
> be an Array (probably resulting from a find), otherwise the plural is  
> not relevant.

I apologize for not posting my actual controller code. This is what I  
was using - note that my instance variable is plural as I do expect to  
receive multiple story objects within an array.

def index  
@stories = Story.find :all  
@critiques = @stories.critiques  
end

The above code renders an error: undefined method `critiques’ for  
#Array:0x231723c, which now makes me think that if the @stories  
variable was not an array, this would work. That’s the only difference  
between my view and controller. Within my view I’m working with each  
individual story and looping through each critique. I ‘believe’ this  
new found logic is correct, and where that answers one question, how  
would I go about pulling the name of the member who provided the  
critique?

Thanks for the replies. I hope to get down to the bottom of this so I  
can keep progressing. 🙂 Thanks again!

~Dustin T.
