Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails semi-complex STI with ancestry data model planning the routes and controllers

I'm trying to figure out the best way to manage my controller(s) and models for a particular use case.

I'm building a review system where a User may build a review of several distinct types with a Polymorphic Reviewable.

Country (has_many reviews & cities)
Subdivision/State (optional, sometimes it doesnt exist,  also reviewable, has_many cities) 
City (has places & review)
Burrow (optional, also reviewable ex: Brooklyn)
Neighborhood (optional & reviewable, ex: williamsburg)
Place (belongs to city)

I'm also wondering about adding more complexity. I also want to include subdivisions occasionally... ie for the US, I might add Texas or for Germany, Baveria and have it be reviewable as well but not every country has regions and even those that do might never be reviewed. So it's not at all strict. I would like it to as simple and flexible as possible.

It'd kinda be nice if the user could just land on one form and select either a city or a country, and then drill down using data from say Foursquare to find a particular place in a city and make a review.

I'm really not sure which route I should take? For example, what happens if I have a Country, and a City... and then I decide to add a Burrow?

Could I give places tags (ie Williamsburg, Brooklyn) belong_to NY City and the tags belong to NY?

Tags are more flexible and optionally explain what areas they might be in, the tags belong to a city, but also have places and be reviewable?

So I'm looking for suggestions for anyone who's done something related.

Using Rails 3.2, and mongoid.

like image 780
ere Avatar asked Mar 22 '12 14:03

ere


1 Answers

I've built something very similar and found two totally different way that both worked well.

Way 1: Country » Subcountry » City » Neighborhood

The first way that worked for me is to do it with Country, Subcountry, City, Neighborhood. This maps well to major geocoding services and is sufficient for most simple uses. This can be STI (as in your example) or with multiple tables (how I did it).

In your example you wrote "Subdivision/State". My two cents is to avoid using those terms and instead use "Subcountry" because it's an ISO standard and you'll save yourself some confusion when another developer thinks a subdivision is a tiny neighborhood of houses, or when you have a non-U.S. country that doesn't use states, but instead uses provinces.

This is what I settled on after many experiments with trying model names like Region, District, Area, Zone, etc. and abandoning these as too vague or too specific. In your STI case it may be fine to use more names.

One surprise is that it's a big help to write associations that go multi-level, for example to say country.cities (skipping subcountry). This is because sometimes the intermediary model doesn't exist (i.e. there's no subcountry). In your STI, this may be trickier.

Also you get a big speedup if you denormalize your tables, so for example my city table has a country field. This makes updating info a bit trickier but it's worth it. Your STI could inmplement an equivalent to this by using tags.

Way 2: Zones that are lists of lat/lng shapes with bounding boxes

The second way is to use an arbitrary Zone model and store latitude longitude shapes. This gives you enormous flexibility, and you can pre-calculate when shapes contain other shapes, or intersect them. So your "drill down" becomes "show me shapes immediately inside this one".

Postgres has some good geocoding helpers for this, and you can speed up lookups by doing bounding boxes of min/max lat/lng. We also stored data like the expected center point of a Zone (which is where we would drop a pin on a map), and a radius (useful for calculating queries like "show me all the x items within y distance).

With this approach we were able to do interesting zones like "Broadway in New York" which isn't really a neighborhood so much as long street, and "The Amazon Basin" which is defined by the river, not a country.

like image 183
joelparkerhenderson Avatar answered Jan 02 '23 06:01

joelparkerhenderson