Here is a problem I've been struggling with for a while, and I know how to solve it with find_by_sql, but I just feel soooo close to being able to set up this association without needing to do any specific SQL, so here I am asking for help. Here is the situation:
- 3 models: City, Zipcode, Contact
- City has_many zipcodes
- Zipcode belongs_to city, has_many contacts
- Contact belongs_to Zipcode
- Zipcode has attribute zip that contains the zip code. Contact also has a zip attribute.
So a city, like Atlanta, would have many zip codes, and each zip code has many contacts with that zip code in their address. The goal is that I could do this: @city.contacts and use the zipcodes as a join table.
Here are my model definitions:
class City < ActiveRecord::Base
has_many :contacts, :through => :zipcodes #this does not work
end
class Contact < ActiveRecord::Base
belongs_to :zipcode, :foreign_key => :zip, :primary_key => :zip
end
class Zipcode < ActiveRecord::Base
belongs_to :city
has_many :contacts, :primary_key => :zip, :foreign_key => :zip
end
And below is what comes from the console to test these associations. Every association works EXCEPT the city.contacts one. You can see the query it generates: it is c orrect, except right before the WHERE zipcodes.id should be zipcodes.zip. When you make that change, this query pulls up the proper records for the association. But h ow can I define the associations such that the query is formed properly? I've spent a couple hours on this.
zip = Zipcode.first Zipcode Load (0.2ms) SELECT
zipcodes
.* FROMzipcodes
LIMIT 1 => #zip.city City Load (0.5ms) SELECT
cities
.* FROMcities
WHERE (cities
.id
= 7) ORDER BY name LIMIT 1 => #zip.contacts Contact Load (0.3ms) SELECT
contacts
.* FROMcontacts
WHERE (contacts
.zip = 30084) => [#acity = City.find 7 City Load (0.3ms) SELECT
cities
.* FROMcities
WHERE (cities
.id
= 7) ORDER BY name LIMIT 1 => #acity.zipcodes Zipcode Load (0.2ms) SELECT
zipcodes
.* FROMzipcodes
WHERE (zipcodes
.city_id = 7) => [#acity.contacts Contact Load (0.3ms) SELECT
contacts
.* FROMcontacts
INNER JOINzipcodes
ONcontacts
.zip =zipcodes
.id WHERE ((zipcodes
.city_id = 7)) => []
NOTE THE EMPTY RESULT ABOVE. KHAAAAAAN!