Use of self reflection to determine possible actions

Is there a way to use either Ruby or Rail's self reflection to return
a list of actions a given controller can respond to?
I found the "methods" method, but it appears to return everything,
including all of the super class methods. I want just the actions a
given controller has defined. I am trying to implement a Roles Based
Access framework and want to have dynamic links based upon what a user
can do. It would be nice if the controllers can tell me what is
possible, and then remove those things the user isn't allowed to do.

Any suggestions?

http://destiney.com/blog/rubyonrails-get-public-actions-from-a-controller

Crispy :

Is there a way to use either Ruby or Rail's self reflection to return
a list of actions a given controller can respond to?

ActionController::Base#action_methods and
ActionController::Base.action_methods

   -- Jean-François.

Neither of the two seem to work.
I get...

Evaluation failed. Reason(s):
    uninitialized constant
ActionWebService::Dispatcher::ActionController::Base

Sometimes this happen.

Where you want to know actions???

Everton,
I wasn't sure I understood your question.
What I'm trying to do is implement a Role Based Access Control (RBAC)
framework.
Basically, a user gets assigned one or more Roles. A Role has a
collection of Rights. A Right is a Controller and Action within in
the applicatoin.
If a user has a given right, the authenticator will allow a redirect
to that Controller and Action.
In the administration section of the application, where Rights are
defined and assigned to Roles, I wanted to provide a drop down list of
all the possible Rights to select from. Ideally, the application
itself should be able to tell me what Controllers and Actions it
provides via self reflection.
This would have been a snap in Smalltalk, but I can't seem to get
something that works in Ruby/Rails.
If one does something like
allowedControllers = ApplicationController.subclasses
you only get the controller that was in context (presumably because
the subclasses method uses ObjectSpace), and its only a string, not
the actual class.
Therefore, I can't loop through the collection and do something like
allowedActions = aController.action_methods
Therefore, i'm a bit frustrated and looking for those wiser than I to
clue me in.

The problem with calling ApplicationController.subclasses is that Rails does not load

classes until they are invoked - so all you see is the current controller. To get a list of

all available controllers, you need to explicitly load them all. Example:

(in your controller)

def load_all_controllers

require RAILS_ROOT + “/app/controllers/application”

Load all the controller files

controller_files = Dir[RAILS_ROOT + “/app/controllers/**/*_controller.rb”]

controller_files.each do |file_name|

require file_name

end

end

This will pull all of the controller definitions in, giving a complete list in ApplicationController.subclasses.

To use the list, you need to iterate over the entries:

def iterate_over_controllers

ApplicationController.subclasses.each do |controller_name|

controller_name.constantize.action_methods.each do |method|

do something with combination of controller_name and method

end

end

end

You may also want to take a look at the User engine (
http://agilewebdevelopment.com/plugins/user_engine
) - even if Engines aren’t your thing, the ideas there could be useful. Note that the engine uses

a rake task to sync available controller/action pairs rather than generating them on the fly.

Hope this helps…

–Matt

On previous post i spoke about similar question:

http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/f6c1b3a546e7e240/40233a3286dfdccf?hl=en&lnk=gst&q=%22Admin+and+Dry%22#40233a3286dfdccf

I have done the same thing that are you speaking about, but
controllers/actions was created on a migration. I think that this
should be moved to a rake task too.

I think that engines like User Engine have problems for me, and so, i
create RBAC system myself. On my system, i have more than just
controller/action or “permissions” models, i have tools_categories
that group actions behind some “tool”. Each permission is maded by
relationships between tools_categories and roles through functions
(where functions is just C-R-U-D at now). The system “introspect”
function of each action based on his name (ugly, but works). When you
specify a permission you just say that some role have access to create
and read, but not update or delete on a specific tool. This is very
simple to use and configure and works fine for me.
To help me, i just add some useful methods to user model, like
canCreate?(action) or canUpdate?(action) and i just overwrite
link_to*** helpers to return “” if user has no access to relative
access.

Note: actions like ‘‘new’’ should be classified as C (create), so links
for new never will appear if the role has no permissions to create.
This give more freedom to write my code, without many IFs on all
views…

I can give you all this code, but it’s in portuguese until now, :frowning: .
I will translate all and move to engine in a few days. If you want to
help me, i will be grateful.

One smallest p.s.:

My approach was so non-intrusive, that all application was created before AC, and so i do the AC system and restrict all data under the system on a complex scope restriction, without any change on code that was made before the system.

Some practices on this system could be “questionable” (abusive use of with_scope, link_to*** that return blank string obviously generate some invalid or ugly html (tables and lists with blank tds/items, etc)), but the clean code and very fast work done pay this price.