# Using :through

**URL:** <https://discuss.rubyonrails.org/t/using-through/2102>\
**Category:** rubyonrails-talk\
**Created:** [September 24, 2006, 3:57pm UTC](https://discuss.rubyonrails.org/t/using-through/2102 "2006-09-24T15:57:06Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 24, 2006, 3:57pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/1 "2006-09-24T15:57:06Z")

</div>

Sorry, cause this is the second post in trying to solve the same problem. Since that other post hasn't received any replies and I have a slightly better understanding I'm trying it again.

In my Position model I have the method company\_id In my Cdetail model I have a method company\_id and another company\_name.

When I'm pulling up queries on the Position table I want to translate the company\_id in Position to the company\_name in Cdetail.

Is this something to use the :through option with or is there another way ?

Stuart

---

<div class="post-metadata">

**Author:** ![Jason\_Norris](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@Jason\_Norris](https://discuss.rubyonrails.org/u/Jason_Norris)\
**Post date:** [September 24, 2006, 4:46pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/2 "2006-09-24T16:46:27Z")

</div>

I assume that Cdetail belongs\_to Position?

If so, you could redefine the company\_id method

def company\_id &nbsp;&nbsp;&nbsp;&nbsp;self.Cdetail.company\_name end

Would this work?

Also, if you wanted to use :select in your Find call, you could do

&nbsp;&nbsp;&nbsp;&nbsp;Position.find(:all, :select =\>'[other fields..], cdetails.company\_name as company\_id', :include =\> 'cdetails')

But now that I'm thinking about it, do you really want to use the field used for the foreign key to do this? That could cause problems.

Jason

Dark Ambient wrote:

---

<div class="post-metadata">

**Author:** ![5MileRadius](https://avatars.discourse-cdn.com/v4/letter/5/ed655f/32.png) [@5MileRadius](https://discuss.rubyonrails.org/u/5MileRadius)\
**Post date:** [September 24, 2006, 4:47pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/3 "2006-09-24T16:47:11Z")

</div>

I can't quite say I followed all of that. I'd recommend posting a copy of the fixture data for both models or a class definition of each model listing the attributes.

Dark Ambient wrote:

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 24, 2006, 5:06pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/4 "2006-09-24T17:06:17Z")

</div>

Model: (showing only relevant lines)

class Position \< ActiveRecord::Base belongs\_to :cdetail

attribute: company\_id

class Cdetail \< ActiveRecord::Base

has\_many :positions

attributes: company\_id, company\_name

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 24, 2006, 5:10pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/5 "2006-09-24T17:10:43Z")

</div>

> I assume that Cdetail belongs\_to Position?

The other way around , Position belong\_to Cdetail

> If so, you could redefine the company\_id method
> 
> def company\_id &nbsp;&nbsp;&nbsp;&nbsp;self.Cdetail.company\_name end
> 
> Would this work?
> 
> Also, if you wanted to use :select in your Find call, you could do
> 
> &nbsp;&nbsp;&nbsp;&nbsp;Position.find(:all, :select =\>'[other fields..], cdetails.company\_name as company\_id', :include =\> 'cdetails')

It might work, what is the [other fields] mean ? or can i just exclude that option ?

> But now that I'm thinking about it, do you really want to use the field used for the foreign key to do this? That could cause problems.
> 
> Jason

I'm not sure , but in looking through my options I thought perhaps I could use it to define the correct association.

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 24, 2006, 5:36pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/6 "2006-09-24T17:36:54Z")

</div>

Maybe this will help, because it seems I like my explanations are not conveying my issue . I created a sql query in mysql to extract the correct information - this query works , so now I need to figure out a way for Rails to perform it.

SELECT cdetails.company\_name FROM positions Inner Join cdetails ON positions.company\_id = cdetails.company\_id

Hope this helps

Stuart

---

<div class="post-metadata">

**Author:** ![Jason\_Norris](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@Jason\_Norris](https://discuss.rubyonrails.org/u/Jason_Norris)\
**Post date:** [September 24, 2006, 6:02pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/7 "2006-09-24T18:02:14Z")

</div>

Like 5MileRadius said, posting your models and possible some controller code would help. But. To get rails to do that query, you could do

Position.find(:all, :select =\> 'cdetails.company\_name as whatever', :include =\> 'cdetails') that will return an array of Position objects.

When you use :select, the string you pass is what is used in Rails' "SELECT" statement, so only those fields will be queried. If you want other things to be retrieved, you must include them in your :select

Jason

Dark Ambient wrote:

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 24, 2006, 7:38pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/8 "2006-09-24T19:38:51Z")

</div>

Could someone explain what posting the models means ? I'm not trying to be funny, but what I posted was pretty much them. Anyway I'll post them here again.

class Position \< ActiveRecord::Base &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :state &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :category &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :edureq &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :expreq &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :pay &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :postlength &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :securityclear &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :term &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :travreq &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :wage &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :user &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :cdetail

&nbsp;&nbsp;def self.current\_openings &nbsp;&nbsp;find(:all) &nbsp;&nbsp;end end

class Cdetail \< ActiveRecord::Base &nbsp;&nbsp;belongs\_to :user &nbsp;&nbsp;has\_many :positions

end

I thought I could put something into the Position associations like this:

belongs\_to:comp\_name, :class\_name=\> "Cdetail", :foreign\_key =\> "company\_name and although it wasn't returning an error it wasn't giving me the name.

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 24, 2006, 10:59pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/9 "2006-09-24T22:59:44Z")

</div>

This is one messy thread. Anyway , I worked out this problem using find\_by\_sql. Why I can't do it through the AR associations is beyond me. I don't know if I feel right using find\_by\_sql, as it doesn't really take advantage of the associations that are in place. Does it have a downside ? I've posted my models as requested below anyway.

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 25, 2006, 2:02pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/10 "2006-09-25T14:02:28Z")

</div>

> I think your original question was, how do I get the the cdetails's company\_name, given a position. Why can't you just do:
> 
> position.cdetail.company\_name
> 
> ?

No, that is just giving me "undefined method `cdetail' for #\<Position:0x4c56748\>"

> "belongs\_to :cdetail" adds an accessor method to Position which results in the Cdetail referenced by the cdetail\_id field in Position (you can change the name of the field with :foreign\_key, if your field is named something other than cdetail\_id).

Well , I've been trying this and it seems to have no effect - continuing to get undefined method - "cdetail"

Here is the relationship defined in Position model belongs\_to :cdetail, :foreign\_key =\> :company\_id

So, in the Position model , the attribute is company\_id and in the Cdetail model, the attribute is company\_id , perhaps having both columns with the same name is confusing the issue.

> if you wanted to access users directly from cdetail (use :foreign\_key and :source if the field names are weird).

I haven't gotten a good feel for the :source option. Reading through the doc it seems to reference another model ?

> Tangent: Is there a reason you're using an unintuitive reference like "cdetail"? Why not just call it a "company", with fields "id" and "name"? Or even "company\_detail"?

Because I didn't think it through and I'm being hard headed 🙂Actually company\_detail maybe a better idea, if that would truly help the association problem. The c in cdetail obviously stands for company. Just in case it seemed my model naming is totally irrelevant.

For the time being I solved the issue by adding the :join option to the find. It's not totally ugly and seems to give me the results. However I'd like to do it, as said above position.cdetail.company\_name.

Stuart

---

<div class="post-metadata">

**Author:** ![David\_A\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/bcef8e/32.png) [@David\_A\_Black1](https://discuss.rubyonrails.org/u/David_A_Black1)\
**Post date:** [September 25, 2006, 2:13pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/11 "2006-09-25T14:13:16Z")

</div>

Hi --

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 25, 2006, 4:14pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/12 "2006-09-25T16:14:28Z")

</div>

> David wrote: \> It seems a little over-engineered, perhaps. Since you have a \> companies table, why not just put the details of the companies in that \> table? Then each position could have a company, which in turn would \> have a name:
> 
> Stuart, just to clarify: Do you have a companies table, which Position and Cdetail reference with their company\_id field? Or is Position.company\_id referencing a Cdetail record identified by it's company\_id field? Or is company\_id not a record id at all, and some other id (like, from another database)?
> 
> --

So many choices 🙂 .. It is Position.company\_id is referencing a Cdetail record with a company\_id field. For sanity sake here are the tables:

cdetails

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 25, 2006, 5:46pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/13 "2006-09-25T17:46:29Z")

</div>

> If company\_id holds a value you're getting from somewhere else, then don't make it your primary key.
> 
> The problem is that you have two "unique" ids for a cdetail, a record id and a company id. Rails uses record ids to build relationship accessor methods, but you have a valid reason to want to use the company id in creating positions, I'm guessing, that the user who creates new positions knows and can input the company id to which the position should belong, but not its record id in the database (and why should they?)

Actually without sounding too screwey, I'm grabbing it out of the session information.

> To keep your database normalized, I would remove the company\_id field from Position and replace it with a cdetail\_id, so you can use all of Rails' relationship goodness. Then override Position's initialize method to get the correct cdetail\_id from a company\_id:
> 
> if cdetail\_id.nil? and company\_id &nbsp;&nbsp;cdetail = Cdetail.find\_by\_company\_id company\_id &nbsp;&nbsp;cdetail\_id = cdetail.id unless cdetail.nil? end

I'm thinking all this wouldn't be necessary. All I'm really doing is taking the user\_id out of the session information and calling that the company\_id. Renaming the position.company\_id to cdetail\_id shouldn't effect the creation of the position. btw, if it means anything, I'm using a hidden field to input this id. You did say the magic words though "normalize the database". Yes that is important.

> Then when you save, the position will refer to the correct Cdetail record (the save will ignore the company\_id property in the Position if there's no corresponding field in the table). Maybe add a validation for cdetail\_id which complains about company\_id?
> 
> Then when you need the company\_id (or, silimlarly, company\_name) for a position, you do:
> 
> position.cdetail.company\_id

K. that makes sense. I'll be trying it shortly and let you know how it works out.

> Again, for clarity, where does the content for the company\_id field come from? If it's entirely internal, I would get rid of it and just use the cdetails' id field as the unique identifier and present the user with a menu of company names (or something).

Again, company\_id in both the positions table and the cdetails table comes from the user id in the session information.

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 25, 2006, 6:52pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/14 "2006-09-25T18:52:44Z")

</div>

Got to run out , but will work on this in a few hours. &nbsp;&nbsp;Let you know how things work out a little later.

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 25, 2006, 9:38pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/15 "2006-09-25T21:38:03Z")

</div>

Followed through a was returned You have a nil object when you didn't expect it! The error occurred while evaluating nil.cdetail

> Forget what I said before. I would set up a has\_one/belongs\_to relationship between User and Cdetail, and a has\_many/belongs\_to relationship between User and Position. That's it. Then to get the Cdetail from a Position, I would do this:
> 
> position.user.cdetail

So here is the models just to show that i followed above correctly: Actually all these relationships existed already.

class User \< ActiveRecord::Base &nbsp;&nbsp;has\_one :cdetail &nbsp;&nbsp;has\_many :positions &nbsp;&nbsp;before\_create :make\_activation\_code

class Position \< ActiveRecord::Base

&nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :user &nbsp;&nbsp;&nbsp;&nbsp;belongs\_to :cdetail

class Cdetail \< ActiveRecord::Base &nbsp;&nbsp;belongs\_to :user &nbsp;&nbsp;has\_many :positions

Maybe I'm doing something wrong here .

stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 26, 2006, 12:34pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/16 "2006-09-26T12:34:40Z")

</div>

I'm not sure I understand why I need to go through User to get what I need out of Cdetail. Anyway, before explaining , let me try and understand it first on my own. However, as suggested I've made some changes, renaming Cdetail to Company

Company has these relevant attributes: id : auto\_incrementing company\_id name

Position has this relevant attribute: company\_id

So what I thought made sense here was to add association like this to Position belongs\_to: company, :foreign\_key =\> company\_id

Then in show, list position.company.name

Maybe it makes sense to go through User but truthfully it's not giving me any better results.

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 26, 2006, 6:09pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/17 "2006-09-26T18:09:57Z")

</div>

bump 🙂

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 26, 2006, 6:22pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/18 "2006-09-26T18:22:23Z")

</div>

> Stuart Fellowes wrote: \> Again, company\_id in both the positions table and the cdetails table \> comes from the user id in the session information.
> 
> Stuart Fellowes wrote: \> Company \> company\_id \> \> Position \> company\_id \> \> So what I thought made sense here was to add association like this to \> Position \> belongs\_to: company, :foreign\_key =\> company\_id
> 
> I think your own naming conventions are confusing you (they're confusing me). As you said before, company\_id holds the id of a record in the users table (so please, please rename it user\_id -- you'll be thankful you did in three months). When you say "Position belongs\_to :company, : foreign\_key =\> :company\_id", you're telling Rails that company\_id holds an id of a record in the companies table, which is not the case.

company\_id DOES hold a record in the companies table. companies:

> id | company\_id | company\_name | address | city | so on ............

So why can I just connect these two tables , even though I realize the id in the companies table is not the standard id as far as AR goes ? Am I crazy and beating a dead horse or can this not be done. I am under the impression there are ways to let AR know of these unusual attribute names ?

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 26, 2006, 7:06pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/19 "2006-09-26T19:06:55Z")

</div>

I know by now ya think I'm crazy but I put it together exactly how recommended. I'm still getting an undefined method for company.

class Company \< ActiveRecord::Base &nbsp;&nbsp;belongs\_to :user end

class User \< ActiveRecord::Base &nbsp;&nbsp;has\_one :company end

class Position \< ActiveRecord::Base ........... &nbsp;&nbsp;&nbsp;belongs\_to :user end

companies table:

> id | user\_id | name |

users table:

> id | company\_id | # I also tried changing this to user\_id

(rebooted server) no dice

I added this to the position.rb controller: def company user.company end

Calling it through: position.company.name %\>

Stuart

---

<div class="post-metadata">

**Author:** ![Dark\_Ambient](https://avatars.discourse-cdn.com/v4/letter/d/e9bcb4/32.png) [@Dark\_Ambient](https://discuss.rubyonrails.org/u/Dark_Ambient)\
**Post date:** [September 26, 2006, 11:17pm UTC](https://discuss.rubyonrails.org/t/using-through/2102/20 "2006-09-26T23:17:10Z")

</div>

Since I tried everything suggested, read and googled with no end in site - I came up with what I think is a viable solution, I made the company id attribute not to auto increment but to use the company id in that column. Seems to work , any possible problems ?

Stuart
