I also have a versioned API. I haven't bumped to the next version yet. But I thought I'd share what I plan to do. This might be a little hairballed. And I have a feeling that this will be more useful to me (to think through my plan) than it is to you. So, sorry about that. But, here goes...
Before I start, I should say that I take a different sort of approach to my controller actions. In my apps, I like to delegate my controller actions to plain old ruby objects that I call 'managers'. Every controller has a 'manager_base'. So, in my controllers, I have something like this:
class ApplicationController < ActionController::Base
private
def do_action(action=nil)
action ||= caller[0][/`.*'/][1..-2]
manager.send("manage_#{action}", self, cookies, request)
end
def manager
base = self.class.name.split('::')
base.pop
base << "#{controller_name.camelize}Managers::ManagerBase"
base.join('::').constantize
end
end
class Api::V1::FooController < ApplicationController
def index
do_action
render_result
end
end
And then I also have:
class ManagerBase
class << self
def manage_index(controller, cookies, request)
sub_out("Index", controller, cookies, request)
end
def manage(controller, cookies, request)
new(controller, cookies, request).manage
end
private
def sub_out(method, controller, cookies, request)
sub_manager(method).manage(controller, cookies, request)
end
end # Class Methods
def initialize(controller, cookies, request)
@controller = controller
@cookies = cookies
@request = request
end
end
class Api::V1::FooManagers::ManagerBase < ManagerBase
class << self
private
def sub_manager(method)
"Api::V1::FooManagers::#{method}Manager".constantize
end
end # Class Methods
end
class Api::V1::FooManagers::IndexManager < Api::V1::FooManagers::ManagerBase
def manage
... do stuff
end
end
If you follow the bouncing ball, here's how my application flow goes:
index gets called on Api::V1::FooController
index calls do_action (inherited from ApplicationController) which, in turn calls manager (also inherited from ApplicationController)
manager returns the Api::V1::FooManagers::ManagerBase class
do_action then calls manage_index on Api::V1::FooManagers::ManagerBase
manage_index calls sub_out which in turn calls sub_manager
sub_manager returns the Api::V1::FooManagers::IndexManager
sub_out then calls manage on Api::V1::FooManagers::IndexManager
manage (the class method - inherited from ManagerBase) creates a new instance of Api::V1::FooManagers::IndexManager and then calls manage (the instance method) on the new instance.
As may or may not be apparent, when I move to Api::V2, I have two opportunities to 'hook' back into the Api::V1 versions of my managers (which is equivalent to using my V1 controller methods - your original question).
First, if I haven't implemented Api::V2::FooManagers::ManagerBase yet, I can cause ApplicationController.manager to fall back to the last implemented version of ManagerBase (i.e., Api::V1::FooManagers::ManagerBase). In which case I'll be using all of the Api::V1::FooManager sub managers (like IndexManager).
Second, if I've implemented Api::V2::FooManagers::ManagerBase but have not yet implemented Api::V2::FooManagers::IndexManager, then I can cause Api::V2::FooManagers#sub_manager to fall back to Api::V1::FooManagers::IndexManager.
Okay, I'm going to stop now. Thanks for the opportunity to think this through out loud. Apologies if it's a totally useless, hot mess.