Topic: Controller module constants (dynamic class loading)

I'm developing a content management system at the moment that bases its permission system on the controllers, actions and IDs of the Rails structure. As such, rather than having to keep my own list of all the controllers and actions in my app, I wrote the below code to automate it:

        @controllers = []
        @cs = ['Choose a controller']
        cs = Dir.entries(RAILS_ROOT + '/app/controllers')
       
        for ctrl in cs
            # check for sub-folders
            if ctrl !~ /[a-z]*\.[a-z]*/
                subs = Dir.entries(RAILS_ROOT + '/app/controllers/' + ctrl)
                for file in subs
                    file = file.sub(/([a-z])/) {|match| match.upcase}
                    file = file.gsub(/_([a-z])/) {|match| match.upcase.sub(/_/, '')}
                    file = file.sub(/.rb/, '')
                   
                    if !['.', '..', 'Application'].include? file
                       
                        # add module
                        file = ctrl.sub(/([a-z])/) {|match| match.upcase} + '::' + file
                       
                        c = Object.const_get(file.gsub(/::/, '')).new
                   
                        @cs << c.controller_name
                        @controllers << {
                            :name => c.controller_name,
                            :methods => c.send(:action_methods).map(&:to_s)
                        }
                       
                    end
                end
                next
            end
           
            ctrl = ctrl.sub(/([a-z])/) {|match| match.upcase}
            ctrl = ctrl.gsub(/_([a-z])/) {|match| match.upcase.sub(/_/, '')}
            ctrl = ctrl.sub(/.rb/, '')

            if !['.', '..', 'Application'].include? ctrl
                c = Object.const_get(ctrl).new
           
                @cs << c.controller_name
                @controllers << {
                    :name => c.controller_name,
                    :methods => c.send(:action_methods).map(&:to_s)
                }
               
            end
           
        end


This has been working fine (though I imagine there may be a cleaner/more efficient way of doing it, so feel free to point out if there is - I'm still learning Ruby/Rails) until I added a module controller Manage::Users and this line broke:
c = Object.const_get(ctrl).new

This is the line that instantiates each controller to then get its actions, though for modules I get this error:

uninitialized constant Manage::UsersController

And so I eventually get to my question: how are 'sub-controllers' named as constants (if they are) or is there a better way of creating new instances of classes where the class name is a variable?

Any suggestions are much appreciated!

Re: Controller module constants (dynamic class loading)

After a bit of digging I've found a suggestion that Rails has a constantize method which should help for classes of the form Whatever::SomeController, but I now get:

Manage::UsersController is not a symbol

Any ideas?

Re: Controller module constants (dynamic class loading)

perhaps try using to_sym before calling constantize as that would coerce the string to a symbol.

My RoR journey  -- thoughts on learning RoR and lessons learned in applying TDD and agile practices.

Re: Controller module constants (dynamic class loading)

Thanks for the suggestion. Someone posted a reply on my blog with this link that sorts it:

http://redcorundum.blogspot.com/2006/05 … stget.html

Now I'm just getting stuck using controller_path hehe - gives this error now:

undefined method `controller_path' for #<Manage::UsersController:0x389e430>

I'll get there eventually big_smile

Re: Controller module constants (dynamic class loading)

All sorted now - controller_path is a class method, not an instance method, so I just had to do (using the qualified_const_get from the link above):

path = qualified_const_get(controller)::controller_path