Я уверен, что вы уже нашли решение для этого ....
Для подобных вещей я нахожу, что прибегаю к денормализации великих предков и не только. Несмотря на то, что это не лучшая практика работы с БД, она значительно упрощает использование с небольшими накладными расходами.
Так, например, ваша таблица местоположений будет иметь столбцы city_id, state_id и country_id, а в случаях, когда типом является «state», city_id равен нулю. а для type = "country" city_id и state_id равны нулю. Тогда в любой момент ваш запрос на поиск всех дочерних элементов данного узла прост, вам просто нужно знать, какой тип узла вы ищете.
Простое before_save может сделать денормализацию.
belongs_to :city, :class_name => "Location", :foreign_key => :city_id
belongs_to :state, :class_name => "Location", :foreign_key => :state_id
belongs_to :country, :class_name => "Location", :foreign_key => :country_id
#might want to throw in some validation that one of the ids is set...
def before_save
self.state_id = self.city.state_id if city_id && city
self.country_id = self.state.country_id if state_id && state
end
В качестве альтернативы вы можете захотеть взглянуть на что-то похожее на реализацию вложенного набора, которая с добавлением двух целочисленных полей (слева и справа) позволяет получить все подузлы для любого узла в иерархии, мой любимый - http://github.com/collectiveidea/awesome_nested_set