我正在尝试创建一个宏" has_accessor_for",它接受一个符号,该符号用作它使用的内部对象的参数(Accessorizer对象)。我遇到的问题是,当多个模块执行has_accessors_for时,参数(范围)最终会被卡在分配给它的最后一个值上。
我在define_method之前添加了一个puts,它显示了它的scope1,然后是scope2 ......但是在define_method中,它始终是scope2。我正在寻找一种基本上封装该变量的方法,这样当第一个模块调用has_accessor_for时,无论何时调用my_wut,它都将绑定到scope1 ...并且无论何时调用my_bleah,它都将绑定到scope2。但正如我所说,现在,my_bleah和my_wut都绑定到scope2--如果我更改MyModel中包含的顺序,那么它们都将绑定到scope1。
class Accessorizer
def initialize(record, scope)
@record = record
@scope = scope
end
def value_for(key)
@record.send key
end
end
module Magic
def has_accessors_for(scope)
accessors = {}
puts "initial: #{scope}"
define_method :get_value_for do |key|
puts "inside method #{scope}"
accessor.value_for key
end
define_method :accessor do
accessors[:scope] ||= Accessorizer.new(self, scope)
end
end
end
module SomeAccessor
extend Magic
has_accessors_for :scope1
def my_wut
get_value_for :wut
end
end
module SomeOtherAccessor
extend Magic
has_accessors_for :scope2
def my_bleah
get_value_for :bleah
end
end
class MyModel
include SomeAccessor
include SomeOtherAccessor
attr_accessor :wut, :bleah
end
m = MyModel.new
m.wut = 'wut'
m.bleah = 'bleah'
m.my_bleah
m.my_wut
initial: scope1
initial: scope2
inside method scope2
inside method scope2
答案 0 :(得分:0)
简短的回答:问题不在于闭包。
答案很长:
define_method :get_value_for do |key|
puts "inside method #{scope}"
accessor.value_for key
end
在给定的类上,只能有一个名为get_value_for
的方法 - 第二个定义将覆盖第一个。
这并不重要,因为你在两种情况下都调用了accessor
,但是这个方法遇到了同样的问题 - 你定义了两次,所以第二个定义会覆盖第一个定义而你最终会只有一个Accessorizer
对象。
我认为你需要在这里重新考虑你的设计。