How to find out which actions are available on a controller?

Hi!

How can I find out which actions a controller supports? I want something
like

is_available( :controller => ‘foo’, :action => ‘bar’ )

which tells me whether a link to

url_for( :controller => ‘foo’, :action => ‘bar’ )

will succeed.

I want to dynamically place links on a page to actions on some specific
controller, but only when this action is actually supported.

Jochen

Jochen Topf [email protected] http://www.remote.org/jochen/
+49-721-388298

Jochen Topf wrote:

will succeed.

I want to dynamically place links on a page to actions on some specific
controller, but only when this action is actually supported.

Since actions are just methods you could use ruby reflection to get all
methods of the controller:

#!/usr/bin/ruby

class Test
def ciao
print “ciao!\n”
end
end

class Hello
#all methods that the class supports:
#print a.methods.sort.join("\n")

#public instance methods:
print Test.public_instance_methods(false)
print “\n”

#or use the respond_to? method to see if a known
#method is supported
#print a.respond_to?(:ciao)
end

Jochen Topf wrote:

will succeed.

I want to dynamically place links on a page to actions on some specific
controller, but only when this action is actually supported.

Jochen

If you’re inside the controller you can call
action_methods.include?(‘bar’). From the outside, it’s
FooController.action_methods.include?(‘bar’).

– stefan

On 19-nov-2005, at 19:14, Jochen Topf wrote:

Jochen
things look a bit nicer and consistent with other functions. I am sure
there must be a function for this somewhere in Rails, because it
has to
do it itself for each request, but I can’t find it.

Jochen, you can take a look at the Inflector - methods as
Inflector::modulize, symbolize, demodulize, constantize etc.
However, it “feels” to me that you are trying to do something which
already IS in rails, you just not know how to get to it.

For instance, have you thought about asking Routes if your route is
mappable and hiding the link if it’s not there? I think if you could
do that
you would get away with much less code that what you are trying to do
now.

On Sat, Nov 19, 2005 at 04:27:39PM +0100, Stefan K. wrote:

If you’re inside the controller you can call
action_methods.include?(‘bar’). From the outside, it’s
FooController.action_methods.include?(‘bar’).

Thanks. That solves half of the problem. But is there also a way to get
from the string ‘foo’ to the controller ‘FooController’? This would make
things look a bit nicer and consistent with other functions. I am sure
there must be a function for this somewhere in Rails, because it has to
do it itself for each request, but I can’t find it.

Jochen

Jochen Topf [email protected] http://www.remote.org/jochen/
+49-721-388298

On Sat, Nov 19, 2005 at 07:35:10PM +0100, Julian ‘Julik’ Tarkhanov
wrote:

controller, but only when this action is actually supported.
from the string ‘foo’ to the controller ‘FooController’? This would

For instance, have you thought about asking Routes if your route is
mappable and hiding the link if it’s not there? I think if you could
do that
you would get away with much less code that what you are trying to do
now.

Well, how would I ask Routes if my route is mappable? I couldn’t find
any documentation about this.

Jochen

Jochen Topf [email protected] http://www.remote.org/jochen/
+49-721-388298

Jochen Topf wrote:

like
controller, but only when this action is actually supported.

Thanks. That solves half of the problem. But is there also a way to get
from the string ‘foo’ to the controller ‘FooController’? This would make
things look a bit nicer and consistent with other functions. I am sure
there must be a function for this somewhere in Rails, because it has to
do it itself for each request, but I can’t find it.

Jochen

Fo top level controllers you can do

Module.const_get('foo'.camelize + "Controller")

If your controller lives inside a module, with a patch like “admin/foo”,
it’s probably

Module.const_get("admin/foo".split("/").collect!{|m|

m.camelize}.join("::") + “Controller”)

But I’m not sure, as I haven’t used modules yet. Maybe there’s a builtin
function for this.

– stefan