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.