This time, some wrassling with relationships between models. Foolishly rejecting the easy option of doing everything the rails way, we hoped to be able to shoehorn a yucky data structure into rails.
We had a table called places, where each place had a two-letter country_code. We wanted to map this to full country names, the data for which was mixed up in the same table. Did say it was yucky.
Using migrations, it was simple to extract the name data, and insert it into a newly created table. In particular,
class LoadCountriesData < ActiveRecord::Migration
def self.up# Probably not the kosher way of doing things, but seems simplest for now.
# Can tidy up later, take a snapshot of entire db schema and contents.execute “insert into countries (code, name) select country_code, name from places where source=’ISO’ “
enddef self.down
Country.delete_all
end
end
Then, how to link the countries and places tables? Immediately assumed a place has_one country, but no, didn’t seem to work. Tried a variety of combinations: belongs_to, foreign_key, association_foreign_key, etc. Ignorance just wasn’t bliss. Googling revealed a vibrant chord of newbie confusion out there (and in here), and finally Duane’s Brain helped begin clear things up.
In actual fact, a place belongs_to :country, in app/models/place.rb. Yes. This means the countries table can sit there knowing nothing but country things, not caring about places, whilst the places table knows about countries, and holds the foreign key that indexes into the countries table. A mnemonic for this might be something like “X holds a foreign_key which belongs_to Y”.
Still not working though. How to tell rails we wanted to hook belongs_to from places.country_code to countries.code, rather than the default rails approach from places.country_id to countries.id? Possibly the first one can be handled by using the foreign_key attribute when specifying belongs_to in places.rb, but to be more railsy we created a new field, places.country_id, and copied the value from places.country_code (using migrations of course). The second part was a bit harder to work out. The auto-generated id field was useless to us since the only references we were using were two-letter country codes. Perhaps we could have done some shenanigans by looking up the id of each country_code in the countries table and writing that back into the places.country_id field. Turns out this was easier for now:
class Country < ActiveRecord::Base
self.primary_key = ‘code’
end
So, there you have it, a morning wasted not doing things the rails way. Migrations are very nice, though.
this feed
1 Comment
May 1, 2007 at 4:12 pm
[...] About in Rails, a place belongs_to a country, and don’t you forget it [...]