在调用上下文中访问局部变量

Accessing local variables in the calling context

在我的代码中,我有几种使用以下模式的方法

def my_method only: [], ignore: []
  something('textvalue') if (only.empty? && ignore.empty?) || (only.any? && only.include?('textvalue')) || (ignore.any? && !ignore.include?('textvalue'))
end

换句话说,我可以选择通过指定 onlyignore 来过滤结果,具体取决于哪个在上下文中更方便。

我想要一种方法来声明一个助手 want 来访问 onlyignore 本地参数,而不必每次都指定它们,理想情况下结果看起来像这样:

def my_method only: [], ignore: []
  something('textvalue') if want('textvalue')
end

这个助手可以用在几个不同的方法中,类,等等。它会以某种方式检查调用点的局部变量,验证 onlyignore 是否存在,然后检查参数是否需要。

是否可以访问调用堆栈并查看那里的局部变量?

有一个 gem binding_of_caller 可以做到这一点。安装 gem 然后执行

require 'binding_of_caller'

def my_method only: [], ignore: []
  something('textvalue') if want('textvalue')
end

def want(value)
  only = binding.of_caller(1).local_variable_get(:only)
  ignore = binding.of_caller(1).local_variable_get(:ignore)
  (only.empty? && ignore.empty?) || (only.any? && only.include?(value)) || (ignore.any? && !ignore.include?(value))
end

但这是一件坏事,因为它会产生非常高的耦合。这真的不是一个好的设计。如果您想这样做是为了实验和玩耍,这很公平,但不要在生产中这样做。

您可以使用 ruby 方法定义来做到这一点

def my_method val, only: [], ignore: [], want: ->(val) { ((only.empty? && ignore.empty?) || (only.any? && only.include?(val))) }
 something(val) if want.call(val)
end

my_method 'value', only: ['value2']
=> false

在这种情况下,您不能将参数传递给 want 吗?

def my_method only: [], ignore: []
  something('textvalue') if want?('textvalue', only, ignore)
end

def want?(string, only, ignore)
  (only.empty? && ignore.empty?) || (only.any? && only.include?(string)) || (ignore.any? && !ignore.include?(string))
end

似乎没有必要比这更复杂?

很多 更易于管理,并且对于其他人来说更易于处理 - 我认为这比避免将几个参数传递给方法重要得多。