Hi
In my application and I need some variation of “attr_accessor” and the like,
so I wrote class functions that create special getter and setter methods
on-the-fly, using module_eval.
If the code I evaled fails during execution (not during
compilation/evaling), the backtrace doesn’t show the filename, and gives a
line number relative to the start of the eval, not the start of the file.
Today I realized that I can “fix” this by doing
_f,_l=FILE,LINE; module_eval %{
…long block of code…
…even more code…
}, _f, _l
instead of plain
module_eval %{
…long block of code…
…even more code…
}
(The reason I use %{} instead of {} is that I use #{} in the evaled
string, just in case someone wonders)
Now, this solves my problem but looks kind of ugly, so I wanted to move it
to a library, and did the following
class Module
def module_eval_withcontext(str)
module_eval(str, FILE, LINE)
end
end
But this has slighly different semantics, because the lexical scope of the
eval has changed, so local variables defined around the place where
module_eval_withcontext is called are no longer available in the evaled
code.
This made me wonder how module_eval works, when it is passed a string
instead of a block. It seems to do the Right Thing, but seems to use some
sort of magic - it seems as if the evaled string would magically be
connected to a binding which is used for evaling…
Could anyone shed light on this, and tell me if there is a way to wrap
module_eval?
greetings, Florian Pflug
PS: I believe it would be a good idea to make module_eval default to FILE and LINE
if no second and third parameter is passed…