[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

binding in ruby1.9

Tim Pease

1/30/2009 6:29:00 PM

Could someone explain why this code does not work in ruby1.9 and
possibly provide a workaround. The end goal is to be able to pass a
binding to an ERb result method that provides a limited set of
variables to the ERb template evaluation.

> cat a.rb

obj = Object.new
class << obj
attr_accessor :foo
end
obj.foo = 'the foo method'
eval "puts foo", obj.__send__(:binding)

> ruby a.rb
the foo method

> ruby1.9 a.rb
a.rb:7:in `eval': undefined local variable or method `foo' for
main:Object (NameError)
from a.rb:7:in `eval'
from a.rb:7:in `<main>'

>ruby1.9 --version
ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-darwin9.6.0]



Blessings,
TwP

3 Answers

Charles Oliver Nutter

1/30/2009 7:57:00 PM

0

Tim Pease wrote:
> Could someone explain why this code does not work in ruby1.9 and
> possibly provide a workaround. The end goal is to be able to pass a
> binding to an ERb result method that provides a limited set of variables
> to the ERb template evaluation.
>
> > cat a.rb
>
> obj = Object.new
> class << obj
> attr_accessor :foo
> end
> obj.foo = 'the foo method'
> eval "puts foo", obj.__send__(:binding)

What an unusual feature to keep coming up.

The contract of binding is that it returns a reification of the caller's
binding. Under 1.8, however, the behavior acted a bit differently, using
the "self" that binding was actually called against. 1.9 has largely
remedied this by always returning the binding of the caller, even if you
__send__(:binding) to another object.

I believe instance_evaling "binding" against the target object would
give you the behavior you're looking for:

[headius @ cnutter:~/projects/ruby-benchmark-suite]
â?? ruby -e "o = Object.new; p o; eval 'p self', o.__send__(:binding)"
#<Object:0x29414>
#<Object:0x29414>
[headius @ cnutter:~/projects/ruby-benchmark-suite]
â?? ruby1.9 -e "o = Object.new; p o; eval 'p self', o.__send__(:binding)"
#<Object:0x3e736c>
main
[headius @ cnutter:~/projects/ruby-benchmark-suite]
â?? ruby1.9 -e "o = Object.new; p o; eval 'p self', o.instance_eval{binding}"
#<Object:0x3e72a4>
#<Object:0x3e72a4>

- Charlie

Tim Pease

1/30/2009 8:20:00 PM

0


On Jan 30, 2009, at 12:56 PM, Charles Oliver Nutter wrote:

> Tim Pease wrote:
>> Could someone explain why this code does not work in ruby1.9 and
>> possibly provide a workaround. The end goal is to be able to pass a
>> binding to an ERb result method that provides a limited set of
>> variables to the ERb template evaluation.
>> > cat a.rb
>> obj = Object.new
>> class << obj
>> attr_accessor :foo
>> end
>> obj.foo = 'the foo method'
>> eval "puts foo", obj.__send__(:binding)
>
> What an unusual feature to keep coming up.
>
> The contract of binding is that it returns a reification of the
> caller's binding. Under 1.8, however, the behavior acted a bit
> differently, using the "self" that binding was actually called
> against. 1.9 has largely remedied this by always returning the
> binding of the caller, even if you __send__(:binding) to another
> object.
>

Okay, that explanation makes sense. My new implementation (following
along with the Kernel docs)

> cat a.rb
obj = Object.new
class << obj
attr_accessor :foo
def get_binding() binding; end
end
obj.foo = 'the foo method'
eval "puts foo", obj.get_binding

> ruby1.9 a.rb
the foo method


Thanks for the insight.

Blessings,
TwP

Charles Oliver Nutter

1/30/2009 9:13:00 PM

0

Tim Pease wrote:
> Okay, that explanation makes sense. My new implementation (following
> along with the Kernel docs)
>
> > cat a.rb
> obj = Object.new
> class << obj
> attr_accessor :foo
> def get_binding() binding; end
> end
> obj.foo = 'the foo method'
> eval "puts foo", obj.get_binding
>
> > ruby1.9 a.rb
> the foo method

Even better!

- Charlie