Reputation: 439
In my code, i have several methods using the following pattern
def my_method only: [], ignore: []
something('textvalue') if (only.empty? && ignore.empty?) || (only.any? && only.include?('textvalue')) || (ignore.any? && !ignore.include?('textvalue'))
end
In other word, i can choose to filter the results either by specifying only
or ignore
, depending on which one is more convenient in the context.
I would like a way to declare a helper want
that access the only
and ignore
local parameters without having to specify them each time, the result would ideally look like this:
def my_method only: [], ignore: []
something('textvalue') if want('textvalue')
end
This helper would be used in several different methods, classes, etc. It would somehow check the local variables at the calling point, validate that only
and ignore
exists, and then check if the parameter is wanted or not.
Is it possible to access the calling stack and look at the local variables there?
Upvotes: 1
Views: 386
Reputation: 12203
In circumstances such as this, couldn't you just pass the args to 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
Doesn't seem to be any need for it to be more complex than that?
That is a lot simpler to manage and for others to deal with going forward - which I'd consider far more important than avoiding passing a couple of args to a method.
Upvotes: 2
Reputation: 739
You can use ruby method definition to do this
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
Upvotes: 2
Reputation: 36860
There is a gem binding_of_caller
which can do this. Install the gem and then do
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
But this is a bad thing to do as it creates very high coupling. It's really not good design. If you want to do this for experimentation and playing around, fair enough, but don't do it in production.
Upvotes: 4