Trying to pick a model setup without ridiculous routes

I am making a site with beer info. I want to have the beer name, brewery and style info for every beer. So they all need to be connected. But, I don't want two styles, i.e. "Pale Ale", "pale ale", "paleale". So I was thinking of making style it's own model and people could choose from a list, and then add one if it wasn't present there.

But, if I had separate models for brewery also the URLs would be nested like crazy. And, I want to be able to look up all the beers of a certain style or from a certain brewery from the URL: example.com/ style/1, or example.com/brewery/1, as well as brew/1.

I know this is an involved question but I just can't wrap my mind around it. I would appreciate any advice. Thanks for reading.

SHORT VERSION:

I want 3 models connected, but I don't want the nested URL craziness. How?

Joel

Have a look at this article: http://weblog.jamisbuck.org/2007/2/5/nesting-resources

Short version: it's better to limit nesting to one level.

Shallow nesting might also be helpful. See section 3.8.4: http://guides.rubyonrails.org/routing.html#restful-routing-the-rails-default

Finally - a subject near and dear to my heart - beer!

One thing to remember about nested resources is its best to nest one level at a time. Otherwise you get very complicated url's.

Depending on how you set the relations, you could have beer as a nested resource of brewery and then set a separate nested resource relationship between beer and style.

  map.resources :beers

  map.resources :breweries

  map.resources :styles

  map.resources :breweries, :has_many => [ :beers ]

  map.resources :beers, :has_many => [ :styles ]

So when you are dealing with breweries, you are only dealing with beers. The same thing happens when you are working with beers, except now you have the styles sub-resource.

Looking at this problem though it seems like a better solution would be a has_and_belongs_to_many relationship between beers,breweries, and styles. A brewery can make several different beers each of a different style after all. To do this you would create a join table that only includes key fields (beers_id, breweries_id, styles_id).

I found a tutorial that should point you in the right direction: http://www.buildingwebapps.com/podcasts/79342-resources-page-links-categories-and-habtm/24793-show-notes

Thanks, I'll read up and come back. Looks like a good solution.

DISCLAIMER: fairly new to Rails myself, but not new to databases, nor to software engineering (and coding concepts such as separation of concerns), so this is sort of written from that POV. The Rails-ish way may be different, but the following is what Makes Sense To Me.

You don't need to have them so closely coupled, nor to have the models nested at all. The brewery, style, etc. could all be parameters of an individual beer. Then you can slap a search on top of your index function. So if you want to know what doppelbocks are made by the Foo Manchoo Brew Krewe, you could do index?style=doppelbock&brewery=Foo%20Manchoo%20Brew%20Krewe (or whatever syntax you decide on for encoding multi-word things). And of course to find all doppelbocks, or all from the FMBK, omit one or the other of the parameters. And of course you could support other parameters, like minrating= some number of stars, possibly separated by rating authority, and so on.

-Dave

Could do all sorts of even more fun things with that too.

map.resources :styles, :has_many => [:beers] map.resources :styles, :has_many => [:breweries] map.resources :breweries, :has_many => [:styles]

Depending on how the user wants to go through (and the design of the backend)...

Could do all sorts of even more fun things with that too.

map.resources :styles, :has_many => [:beers] map.resources :styles, :has_many => [:breweries] map.resources :breweries, :has_many => [:styles]

Depending on how the user wants to go through (and the design of the backend)...

Could do all sorts of even more fun things with that too.

map.resources :styles, :has_many => [:beers] map.resources :styles, :has_many => [:breweries] map.resources :breweries, :has_many => [:styles]

Depending on how the user wants to go through (and the design of the backend)...