Access variable from the block's scope inside a method call in Ruby -
i trying create minitest assertion similiar rails assert_difference checks differences not numeric one.
here current implementation:
minitest::assertions.module_eval def assert_changed(expression, &block) unless expression.respond_to?(:call) expression = lambda{ eval(expression, block.binding) } end old = expression.call block.call refute_equal old, expression.call end end now in test suite call doing following:
# working username = 'jim' assert_changed lambda{ username } username = 'bob' end # not working username = 'jim' assert_changed 'username' username = 'bob' end the first call assert_changed using lambda (or proc) works fine. second call using string variable name not working.
when hits line: expression = lambda{ eval(expression, block.binding) } keep getting error typeerror: no implicit conversion of proc string. can please explain me how work?
note: got eval(expression, block.binding) idea rails assert_difference method.
when hits line:
expression = lambda{ eval(expression, block.binding) }keep getting errortypeerror: no implicit conversion of proc string.
i'm reasonably sure not error when hitting line rather when hitting one:
old = expression.call so, exception not triggered assignment, rather later, when proc called , eval gets executed.
at point, call proc stored in expression. proc stored in expression looks this:
eval(expression, block.binding) the first argument kernel#eval must implicitly convertible string (i.e. responds to_str), proc. ergo, typeerror.
the easiest way make work rename variable:
new_expression = expression unless expression.respond_to?(:call) new_expression = lambda{ eval(expression, block.binding) } end old = new_expression.call block.call refute_equal old, new_expression.call personally, have written more this:
module minitest::assertions def assert_changed(expression, &block) new_expression = if expression.respond_to?(:call) expression else -> { block.binding.eval(expression) } end old = new_expression.() block.() refute_equal old, new_expression.() end end without (useless) module#module_eval, , using call operator syntax , -> stabby lambda literal syntax.
Comments
Post a Comment