# HABTM Reading Rows From Two Tables

**URL:** <https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354>\
**Category:** Rails\
**Created:** [December 24, 2006, 5:26pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354 "2006-12-24T17:26:11Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 24, 2006, 5:26pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/1 "2006-12-24T17:26:11Z")

</div>

I’m a newbie and loving rails but I’m stuck.

All I want to do is to be able to show in my “list.rhtml” view the  
information between two tables who both have a HABTM relationship. So  
this is what I have as follows.

* * *

## TABLES

# Projects

create\_table “projects”, :force =\> true do |t|  
t.column “title”, :string  
t.column “description”, :text  
end

# Users

create\_table “users”, :force =\> true do |t|  
t.column “first\_name”, :string  
t.column “last\_name”, :string  
end

# Projects\_Users

create\_table “projects\_users”, :force =\> true do |t|  
t.column “project\_id”, :integer, :default =\> 0, :null =\> false  
t.column “user\_id”, :integer, :default =\> 0, :null =\> false  
end

* * *

## MODELS

class Project \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :users  
end

class User \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :projects  
end

* * *

## CONTROLLER

# Projects\_Controller

# I have the generic scaffold running my list view

def list  
@project\_pages, @projects = paginate :projects, :per\_page =\> 10  
end

# list.rhtml

# I just want to be able to pull the projects and users that belong to

the project into a view.

# Some projects may have 3 or 4 users.

# so I have this

\<% for project in @projects %\>  
\<%= project.title %\>  
  
\<%= project.users %\>  
  
\<% end %\>

# Which outputs this when you run it…

Project 1

# 

Project 2

## 

Project 3

# 

Project 4

# Which from the database is somewhat accurate. I have two users in

“project 2” but for some reason ROR won’t let me access the information  
about them so it only shows them as “##”, but those are users. Here is  
my DB table below.

# projects\_users - DB

project\_id user\_id  
1 1  
2 2  
2 3  
3 1

# What I want to achieve is something like this .

# 

\<% for project in @projects %\>  
\<%= project.title %\>  
  
\<%= project.users.first\_name %\>  
  
\<% end %\>

\*\*When I try to run this code above it gives me an error saying  
undefined method `first\_name’ for User:Class

The syntax looks somewhat correct, but I’m not doing it right.

Any help on my set-up I would appreciate it.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 24, 2006, 7:50pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/2 "2006-12-24T19:50:20Z")

</div>

I’m pretty new to Rails as well, but I think you need another for loop  
to iterate over all the users. The experssion project.users refers to  
a collection of users which doesn’t have a first name. I would do  
something like this:

\<% for project in @projects %\>  
\<%= project.title %\>  
  
\<% for user in project.users %\>  
\<%= user.first\_name %\>&nbsp  
  
\<% end %\>  
\<% end %\>

Hope that helps.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 24, 2006, 9:06pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/3 "2006-12-24T21:06:28Z")

</div>

Rather than trying to flatten the array Rails lets the user decide how  
to handle it. This is a wise decision as many values may be  
dynamically looked up during render.

For example, say you wanted to display the name of the who created the  
user:

\<% for project in @projects %\>  
\<%= project.title %\>  
  
\<%= project.user.first\_name %\>  
  
\<%= project.user.added\_by.user.first\_name %\>  
  
\<% end %\>

Since the relationship can be extremely complex and circular, there is  
no way to determine what the user wants beforehand and it would in  
inefficient to try.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 24, 2006, 8:14pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/4 "2006-12-24T20:14:21Z")

</div>

Hey Mike,

That totally worked.

Some additional thought…  
You know for some reason I figured when you do a HABTM relationship  
that an array would have both tables contained and you could access  
them using just 1 loop. As I outlined in my attempted solution below:

\<% for project in @projects %\>  
\<%= project.title %\>  
  
\<%= project.users.first\_name %\>  
  
\<% end %\>

Your soultion works but it does require 2 loops. I just wonder do you  
really need to use 2 loops. I’m trying to follow the whole DRY  
principle and it seems too repeatative and it should be 1 loop.

Just a thought.

I’ll just leave this posted to see if anyone else see other ways to do  
it.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 24, 2006, 11:24pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/5 "2006-12-24T23:24:38Z")

</div>

Hey,

Re: Your example  
So you have one loop pulling in information from two tables?  
Are you suggesting this is how it should be done or should it be like 2  
loops as shown in the above entry?

Or are you suggesting the data is too complex between the two tables  
and you really can’t pull it in at once because you get code like this.  
\<%= project.user.added\_by.user.first\_name %\>

any feedback would be appriecated

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 25, 2006, 11:00pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/6 "2006-12-25T23:00:33Z")

</div>

Yes - this is one loop pulling information rom multiple tables (the  
actual number depends on the underlying schema).

Unfortunately, here is no single answer to your question. Two loops  
should be used when it is unclear how many (sub) entries there may be.  
One loop is fine if you _know_ there will only be one entry. It all  
comes down to how your data is modeled.

If you pull all the possible information in a single table (like a  
spreadsheet) the results could be enormous because the framework needs  
to map all the possible combinations and collate them. If you have  
_any_ circular references the resulting table will be infinite.  
Follow?

In you original example, one loop if fine if every project has one  
user, which is almost certainly not the case.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 25, 2006, 11:16pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/7 "2006-12-25T23:16:35Z")

</div>

Now that you further explained it, I understand a bit more. Thanks for  
the extra feedback.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 26, 2006, 7:58pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/8 "2006-12-26T19:58:18Z")

</div>

I don’t think this violates DRY at all. Those two loops are doing two  
different things, one displays projects and one displays users. But I  
can see how this is a little cluttered. If you really want to get rid  
of the second for loop you could use a partial template.

I’m not actually running the code I’m giving you here so there might be  
a couple bugs, but this is the basic idea.

First of all lets change the way you’re displaying the project list to  
make it a little less trivial. Perhaps you want the user’s names to be  
in a list under each project. So the original template code looks like  
this:

\<% for project in @projects %\>

## \<%= project.title %\>
  

\<% for user in project.users %\> - \<%= user.first\_name %\>
\<% end %\>
  
\<% end %\>

Then you abstract the function of displaying a single user into another  
rhtml file called \_user.rhtml (the underscore prefix means it’s a  
partial template.) \_user.rhtml would look something like this:

- \<%= user.first\_name %\>

Then you can change the original template to use the new partial  
template. One of the nice features of using a partial is that it  
allows you to pass in a collection to the render method which does the  
iteration automatically for you. The new project list template would  
look like this:

\<% for project in @projects %\>

## \<%= project.title %\>
  

 \<%= render(:partial =\> "user", :collection =\> project.users)%\>
  
\<% end %\>

Is that simpler than the previous example? I don’t know. You’ve used  
the render method to take the nested loop out of your template, but  
you’ve also added another file to project. To me the extra for loop is  
still readable and I think it’s overall less complex than adding  
another file to maintain. If however you had multiple places in your  
app where you were displaying lists of users this could be valuable  
because then it really would be helping you adhere to the DRY principle.

---

<div class="post-metadata">

**Author:** ![newbie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dc4da7/32.png) [@newbie](https://www.ruby-forum.com/u/newbie)\
**Post date:** [December 26, 2006, 9:10pm UTC](https://www.ruby-forum.com/t/habtm-reading-rows-from-two-tables/80354/9 "2006-12-26T21:10:30Z")

</div>

Hey

Re: Partials  
That is a very interesting technique for using partials. It does look  
like a lot of work but I do have other areas where I need to bring up  
that list.

So many new concepts to learn in ROR but this one is good.

I think I’ll need to get the basics up and running and then go through  
the code and start recfactoring it so it’s clean.

thanks for the extra feedback
