Routes.recognize_path on more complicated Routes

For a permissions system i'm writing i'm extending the standard link_to
helpers to check if a user has a permission to perform that action
before displaying a link to clean-up my code so i don't have to put if
checks all over them.

I'm trying to use..

ActionController::Routing::Routes.recognize_path(url, :method => method)

to get the action and controller out so i can check those permissions.

The problem im having is when it comes to more complicated routes the
recognize_path method gets things mixed up e.g.

/admin/users/60/edit - Controller: admin/users | Action: 60 | Id: edit -
/admin/users/60 - Controller: admin/users | Action: destroy | Id: 60 -
/admin/users/60/ban - Controller: admin/users | Action: 60 | Id: ban -

As you see the ban link has the action and id the wrong way round.

Is there a correct way around this rather than just swapping the 2
values round?

Also when doing a nested route like....


It errors saying "Only get, put, and delete requests are allowed." even
though that route works perfectly fine in a view.

The projects currently running on rails 2.0.1 if that helps.


Hi Danny,

good to see that someone is trying to achieve EXACTLY the same thing
like me. I have even tried to dig deep in the link_to implementation to
solve this, but it is more than black magic and I soon gave up. Do you
have any new ideas regarding the problem?


Hi Jakub

Here's the implementation i ended up with. Its not very clean but it
does the job.

[code] def link_to(*args, &block)
    unless params[:controller] =~ /admin/
      if args.size > 2
        super if action_allowed(args[1], args[2]["method"])
        super if action_allowed(args[1])

  def link_to_remote(name, options = {}, html_options = nil)
    unless params[:controller] =~ /admin/
      super if action_allowed(options[:url], options[:method])

  def action_allowed(url, method = :get)
    return false unless current_user

    path = ActionController::Routing::Routes.recognize_path(url, :method
=> method) rescue nil

    return true unless path

    return true if current_user.roles.find(:first, :conditions =>
["unrestricted = ?", true])

    permissions = Permission.find(:all, :conditions => ["role_id in

    if path[:action] =~ /^\d+$/
      perm = { |p| p.controller == path[:controller]
&& p.action == path[:id] }.first
      perm = { |p| p.controller == path[:controller]
&& p.action == path[:action] }.first

    return true if perm