views:

64

answers:

1

I have following routes.

pota.resources  :on_k,
                :as => ':klass',
                :path_prefix => 'pota/klass',
                :controller => 'main'

When I do rake routes this is what I get for show method:

pota_on_k GET    /pota/klass/:klass/:id(.:format)             
                 {:action=>"show", :controller=>"pota/main"}

Above code works fine in rails 2.x . However if I am using rails3 then I get following error

ActionController::RoutingError: No route matches 
{:action=>"show", :controller=>"pota/main", :klass=>"vehicle/door", :id=>1}

Notice that I am passing 'vehicle/door' as :klass. If I pass a standard model like :klass => 'pet' then it works fine. However if I pass a nested model name like :klass => 'vehicle/door' then I get route error in rails3.

I guess that is because I have '/' in the value . I can solve that by having a regex but I might also pass :klass which is not nested.

On a class like Vehicle::Car I do

Vehicle::Car.underscore #=> vehicle/car
"vehicle/car".camelize.constantize #=> Vehicle::Car

This underscore and camelize/constantize on the other side makes it easier to pass nested class name.

Any idea on how to go about fixing it for rails3?

+2  A: 

STOP!

Think about what you're doing here - you should not be calling constantize on url parameters. Assuming that you're likely to be calling find on the result you're basically giving a hacker a way to query every ActiveRecord model in your application.

A better way is to use meta programming to dynamically build static routes that can't be hacked, e.g:

  %w[pet vehicle/car vehicle/bike].each do |klass|
    resources :pota,
      :path => "pota/#{klass.pluralize}",
      :as => "pota_#{klass.tr('/','_').pluralize}",
      :defaults => { :klass => klass }
  end

Then you can add a helper method that calls the appropriate named route helper to generate urls based upon a passed model instance.

pixeltrix