撤消在 rendering_controller 上设置的实例变量 (render_anywhere gem)
Revoking instance variable set on rendering_controller (render_anywhere gem)
这个问题的这个特定用例可能会导致 github 问题,但我的问题比您将看到的特定用例更广泛,所以请耐心等待!
我在一个项目中使用 render_anywhere
gem,我发现我需要撤销在下一次迭代发生之前在循环内部设置的实例变量(使用 render_anywhere
的对象存在于循环之外,因此变量保留在范围内)。
如果可能,我宁愿避免为循环的每次迭代重新初始化对象。
set_instance_variable
方法的工作原理如下所示(摘自 rubydoc):
# File 'lib/render_anywhere.rb', line 20
def set_instance_variable(var, value)
rendering_controller.class_eval do
attr_accessor :"#{var}"
end
rendering_controller.public_send("#{var}=", value)
end
所以我想我需要使用 this answer:
中描述的方法删除 attr_accessor
undef :"#{var}"
undef :"#{var}="
所以我的问题确实是双重的:
- 一旦设置了实例变量,上述方法是否是从
rendering_controller
中删除属性 read/write 方法的最佳方法?
attr_accessor
会做其他 undef
不会 'clean up' 的事情吗
attr_accessor
是一个 "macro",它简单地为同名的 ivar 定义了 getter 和 setter 方法:
# This line...
attr_accessor :hello
# ...is equivalent to these
def hello
@hello
end
def hello=(value)
@hello = value
end
因此,您需要撤消的 set_instance_variable
代码的效果是:
- 正在创建 getter
var
- 正在创建 setter
var=
- 正在用
value
参数中的值初始化 ivar @var
请注意,set_instance_variable
方法在 控制器实例 上下文中执行所有这些操作,而不是控制器 class 上下文(尽管令人困惑 class_eval
).
您必须执行类似这样的操作才能撤消上述所有操作:
def unset_instance_variable(var)
rendering_controller.remove_instance_variable("@#{var}") if instance_variable_defined?("@#{var}")
rendering_controller.class_eval { remove_method(var) } if rendering_controller.respond_to?(var)
rendering_controller.class_eval { remove_method("#{var}=") } if rendering_controller.respond_to?("#{var}=")
end
如果您想避免猴子补丁,请考虑将 rendering_controller
作为参数发送给此方法。
这个问题的这个特定用例可能会导致 github 问题,但我的问题比您将看到的特定用例更广泛,所以请耐心等待!
我在一个项目中使用 render_anywhere
gem,我发现我需要撤销在下一次迭代发生之前在循环内部设置的实例变量(使用 render_anywhere
的对象存在于循环之外,因此变量保留在范围内)。
如果可能,我宁愿避免为循环的每次迭代重新初始化对象。
set_instance_variable
方法的工作原理如下所示(摘自 rubydoc):
# File 'lib/render_anywhere.rb', line 20
def set_instance_variable(var, value)
rendering_controller.class_eval do
attr_accessor :"#{var}"
end
rendering_controller.public_send("#{var}=", value)
end
所以我想我需要使用 this answer:
中描述的方法删除attr_accessor
undef :"#{var}"
undef :"#{var}="
所以我的问题确实是双重的:
- 一旦设置了实例变量,上述方法是否是从
rendering_controller
中删除属性 read/write 方法的最佳方法? attr_accessor
会做其他undef
不会 'clean up' 的事情吗
attr_accessor
是一个 "macro",它简单地为同名的 ivar 定义了 getter 和 setter 方法:
# This line...
attr_accessor :hello
# ...is equivalent to these
def hello
@hello
end
def hello=(value)
@hello = value
end
因此,您需要撤消的 set_instance_variable
代码的效果是:
- 正在创建 getter
var
- 正在创建 setter
var=
- 正在用
value
参数中的值初始化 ivar@var
请注意,set_instance_variable
方法在 控制器实例 上下文中执行所有这些操作,而不是控制器 class 上下文(尽管令人困惑 class_eval
).
您必须执行类似这样的操作才能撤消上述所有操作:
def unset_instance_variable(var)
rendering_controller.remove_instance_variable("@#{var}") if instance_variable_defined?("@#{var}")
rendering_controller.class_eval { remove_method(var) } if rendering_controller.respond_to?(var)
rendering_controller.class_eval { remove_method("#{var}=") } if rendering_controller.respond_to?("#{var}=")
end
如果您想避免猴子补丁,请考虑将 rendering_controller
作为参数发送给此方法。