我在删除我在rails插件中引入的一些重复时遇到了问题。
下面的代码以相同的方式修改ActiveRecord的查找和计算方法,但我一直无法删除重复。
下面的查找和计算方法使用super关键字,这是一个障碍,因为super关键字只能用于调用与调用方法共享同名的方法,所以我不能将super关键字移动到查找和计算共享的方法。
接下来我尝试使用超类ActiveRecord对find和计算类方法进行别名,但是,我无法为别名获得正确的语法。如果有人能告诉我,那将是一个很大的帮助。
如果你有更好的方式完成这项工作,我也很乐意发帖。
下面我将代码略微调整一下以突出显示问题:
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
答案 0 :(得分:1)
重构此代码的最佳方法是保持find
和calculate
不变,然后使用类级函数添加应用包装。
这是粗略的草图,没有你的模块和mixin逻辑:
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
。)
答案 1 :(得分: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
答案 2 :(得分:0)
只是为find方法添加别名:
module SingletonMethods
def find(*args)
some_method_1
super *args.push(options)
some_method_2
end
alias :calculate :find
end