Topic: Non-invokeable subclasses of ApplicationController...

I have multiple controllers that need to share some code and filters, however this code isn't universal to the application.  So the solution is to add an intermediate subclass between ApplicationController and these controllers.  However, like ApplicationControlller, these intermediate subclass should never be dispatched to by the routing.

Is there a normal Railish way of doing this?  The first thing that comes to mind is to name the file and class something other than *Controller[.rb], ie something like

class AdminBase < ApplicationController
end
class CompetitionController < AdminBase
end
class FeeController < AdminBase
end
....

Thus the AdminBase class can hold the functionality, but rails won't find it as its outside the naming convention.  This seems a little hackish though, but is it the normal way to do it?

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

Re: Non-invokeable subclasses of ApplicationController...

How about just put the shared code in a module and include it in the appropriate controllers?

module AdminBase
  # methods here
end

class CompetitionController < ApplicationController
  include AdminBase
end

class FeeController < ApplicationController
  include AdminBase
end

Last edited by ryanb (2006-08-14 10:11:54)

Railscasts - Free Ruby on Rails Screencasts

Re: Non-invokeable subclasses of ApplicationController...

Hmm that does sound more Rubyish.  One other complication (in my head, as I don't fully grok the dual uses of modules yet namespaces and mixins):

All of these controllers are already inside a module/namespace ie
its actually

class AdminBase < ApplicationController
end
class Admin::CompetitionController < AdminBase
end
class Admin::FeeController < AdminBase
end
....

Does that change anything about how/where I should locate the mixin module?

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

Re: Non-invokeable subclasses of ApplicationController...

I think you can do it either way. Placing it in the Admin module might be best.

module Admin::Base
  # etc...
end

class Admin::CompetitionController < ApplicationController
  include Admin::Base
end


From my understanding you need to include the entire namespace (Admin::Base) unless you do it this way:

module Admin
  module Base
  end

  class CompetitionController < ApplicationController
    include Base
  end
end


I think, someone please correct me if I'm wrong, you can define methods in the Admin module itself which would then be accessible by those inside the module, but they are private methods.

You may not want to use modules if you want to inherit the before_filter and such. There's an article on subclassing Controller's which you may want to take a look at.

Railscasts - Free Ruby on Rails Screencasts

Re: Non-invokeable subclasses of ApplicationController...

Yes, I'm setting before filters in the intermediate class, just like that article.  The author of that article glossed over the issue of the intermediate controller being resolvable by routes, which is a bad thing.  So I guess I'll stick with my current approach, with a non-railish name that doesn't get resolved.

Thanks.

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

Re: Non-invokeable subclasses of ApplicationController...

I should mention that you can't add actions into a module because Rails automatically calls hide_action (or something similar) for every method defined in a module. You can probably hack around this, but it might help decide on whether a class or module is the best fit for your situation. See the docs for details.

Railscasts - Free Ruby on Rails Screencasts