I’m having trouble removing some duplication I’ve introduced in a rails plugin.
The code below modifies the find and calculate methods of ActiveRecord in the same way, but I’ve been unable to remove the duplication.
The find and calculate methods below make use of the super keyword which is one hurdle as the super keyword can only be used to call a method sharing the same name as the calling method, so I can’t move the super keyword to a method shared by find and calculate.
So next I tried aliasing the find and calculate class methods from the superclass ActiveRecord, however, I’ve not been able to get the syntax right for the aliasing. If someone could show me that, it would be a great help.
If you’ve got a better way entirely of doing this I’d love for you to post that too.
Below I’ve trimmed the code down a little to highlight the problem:
module Geocodable #:nodoc: def self.included(mod) mod.extend(ClassMethods) end module ClassMethods def acts_as_geocodable(options = {}) extend Geocodable::SingletonMethods end end module SingletonMethods def find(*args) some_method_1 super *args.push(options) some_method_2 end # TODO: Remove duplication of find above and calculate below. def calculate(*args) some_method_1 super *args.push(options) some_method_2 end end end
Your best way to refactor this code is to leave
findandcalculateunchanged, and add apply the wrapping using a class-level function.Here’s rough sketch, without your module and mixin logic:
Note that this will need to be modified if
Bhas already overriddenfindorcalculate.To use this code, first make your version work correctly, then modify it to use
define_method. (And if you need extremely high performance, you may need to use one of the*_evalfunctions to create the wrappers instead ofdefine_method.)