Dynamic generation of routes based on db contents

Hello all,

I am working on a project that requires the ability to dynamically add
one-level routes based on person name and city.

So, at any given time, someone might go to:

http://www.myapp.com/JakeCutter
http://www.myapp.com/LosAngeles

And the app needs to be smart enough to determine whether the data
passed after / is a user name or a city name.

Each of these potential values are stored in the database, so my first
thought was to dynamically generate it in routes.rb using AR.

User.find(:all).each do |u|
map.connect “/#{u.first_and_last_name}”,
:controller=>UsersController, :action=>:detail, :id=>u.id
end

Location.find(:all).each do | loc |
map.connect “/#{loc.city}”, :controller=>LocationController,
:action=>:detail, :id=>loc.id
end

This works conceptually, but my User model uses betternestedset and
would throw an error upon server startup (acts_as_nested_tree not
defined), so I tried adding this to routes.rb:

class User < ActiveRecord::Base;end
class Location < ActiveRecord::Base;end

Voila! Except for the fact that now, the rest of the app wouldn’t
work (not exactly sure why…I presume this caused some wonkiness with
initialization, but since I’m just re-opening and not re-defining I
would think this would still work).

Anyway, so my next idea was to create a routing controller, simply
route everything one deep to it, and let it do the lookups and then
the appropriate redirect_to. However, I’m afriad of the performance
impacts of going this route. It should only add one db lookup and one
redirect, but I think the redirect would likely be expensive.

I guess I forward this to the group with hopes that someone has faced
this problem before. My questions in order would be:

  1. Am I going in the completely wrong direction here?
  2. Have any idea why betternestedset is throwing this area?
  3. How much overhead do you think to routing controller approach would
    add.
  4. Is there a better way?

Thanks for any help you can provide!

Thanks!
Jake

Not sure what problem you’re having with ‘the rest of the app [not
working]’ but I have experienced issues when loading classes at
startup (environment.rb, initializers, etc) in development. The
issue relates to the way in which classes are reloaded in dev. Short
version is that you end up with weird ‘type mismatch’ problems even
when you’ve got the correct class. If that’s what you’re seeing then
you can work around it by turning on class_caching in
development.rb… as long as you realize you’ll have to restart your
server for just about any dev change.

If the problem is routing (ie., none of the urls work) then it may be
related to the placement of your code in routes.rb. Try pushing it
toward the bottom.

Last question, though… is there a really, really compelling reason
to use urls like this as opposed to something like
http://www.myapp.com/users/JackCutter and
http://www.myapp.com/locations/LosAngeles?

The latter are pretty easy to produce. All you have to do is override
to_param on the User/Location model. The nice thing is that you can
still use the typical named routes. So, for example, the named route
to Rome (all routes lead to Rome!):

class Location < ARec::Base
attr_readonly
before_create :dasherize_name

def to_param
self.dasherized_name
end

protected
def dasherize_name
self.dasherized_name = self.name.downcase.gsub(/\s+/,
‘_’).dasherize
end
end

@rome = Location.find(…)
location_path(@rome)

=> …/locations/rome

And in the controller

def show
@location = Location.find_by_dasherized_name params[:id]
end

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs