1

我无法删除我在 rails 插件中引入的一些重复项。

下面的代码以相同的方式修改了 ActiveRecord 的 find 和 calculate 方法,但我一直无法删除重复项。

下面的 find 和 calculate 方法使用了 super 关键字,这是一个障碍,因为 super 关键字只能用于调用与调用方法同名的方法,所以我不能将 super 关键字移动到共享的方法通过查找和计算。

所以接下来我尝试对超类 ActiveRecord 中的 find 和 calculate 类方法进行别名处理,但是,我无法获得别名的正确语法。如果有人可以告诉我,那将是一个很大的帮助。

如果您有更好的方法来完全做到这一点,我也希望您也发布它。

下面我对代码进行了一些精简以突出问题:

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
4

3 回答 3

1

重构此代码的最佳方法是保持不变,findcalculate使用类级函数添加应用包装。

这是粗略的草图,没有您的模块和混合逻辑:

class A
  def find x
    puts 'finding'
  end

  def calculate x
    puts 'calculating'
  end
end

class B < A
  def self.make_wrapper_method name
    define_method name do |*args|
      puts "entering"
      result = super *args
      puts "exiting"
      result
    end
  end

  make_wrapper_method :find
  make_wrapper_method :calculate
end

请注意,如果B已经覆盖find或,则需要对其进行修改calculate

要使用此代码,首先使您的版本正常工作,然后将其修改为使用define_method. (如果您需要极高的性能,您可能需要使用其中一个*_eval函数来创建包装器而不是define_method.)

于 2009-02-18T14:20:22.607 回答
1

这是我最终选择的选项,感谢 emk 的指导以达到这一点!

module Geocodable

  def self.included(mod)
    mod.extend(ClassMethods)
  end

  module ClassMethods
    def acts_as_geocodable(options = {})
      geoify_query_methods
    end

    private
      # This is where the duplication has been removed
      def geoify_query_methods
        class << self
          [:calculate, :find].each do |method_name|
            define_method method_name do |*args|
              some_method_1
              super *args.push(options)
              some_method_2
            end
          end
        end
      end

  end
end
于 2009-02-26T07:42:29.333 回答
0

只是别名 find 方法:

module SingletonMethods
  def find(*args)
    some_method_1
    super *args.push(options)
    some_method_2
  end
  alias :calculate :find
end
于 2009-02-19T11:12:41.990 回答