# Ruby eval function

**URL:** <https://rubytalk.org/t/ruby-eval-function/58304>\
**Category:** ruby-talk\
**Created:** [27 April 2010 11:30 UTC](https://rubytalk.org/t/ruby-eval-function/58304 "2010-04-27T11:30:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![kevid](https://avatars.discourse-cdn.com/v4/letter/k/e480ec/32.png) [@kevid](https://rubytalk.org/u/kevid)\
**Post date:** [27 April 2010 11:30 UTC](https://rubytalk.org/t/ruby-eval-function/58304/1 "2010-04-27T11:30:14Z")

</div>

Hi all,

I have the code below from "mechanize gem" [the file is module.rb].  
am a newbie in ruby. Could anyone help me redesign the code below to  
use either  
(a) block eval OR (b) not use eval at all.

Thoughts ?

class Module  
&nbsp;&nbsp;def attr\_finder(\*syms)  
&nbsp;&nbsp;&nbsp;&nbsp;syms.each do |sym|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class\_eval %{ def #{sym.to\_s}(hash = nil)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if hash == nil  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@#{sym.to\_s}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@#{sym.to\_s}.find\_all do |t|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found = true  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash.each\_key \{ |key|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found = false if t.send(key.to\_sym) !=  
hash[key]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [27 April 2010 12:01 UTC](https://rubytalk.org/t/ruby-eval-function/58304/2 "2010-04-27T12:01:10Z")

</div>

It's pretty reasonable to use eval in the code you provide. I think the  
method it defines will be faster because there is no closure created.

But if you really want to avoid it:

class Module  
&nbsp;&nbsp;def attr\_finder(\*syms)  
&nbsp;&nbsp;&nbsp;&nbsp;syms.each do |sym|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(sym) do |\*args|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val = instance\_variable\_get("@#{sym}")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return val if args.empty?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash = args.first  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val.find\_all do |t|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found = true  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash.each\_key { |key|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found = false if t.send(key) != hash[key]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

# Test  
class Foo  
&nbsp;&nbsp;attr\_finder :bar  
end

f = Foo.new  
f.instance\_eval { @bar = ["a","bb","cc"] }  
puts f.bar  
puts f.bar(:length =\> 2)

I would also be inclined to simplify your finder loop to this:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash = args.first  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val.find\_all { |t| !hash.find { |k,v| t.send(k) != v } }

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [27 April 2010 13:26 UTC](https://rubytalk.org/t/ruby-eval-function/58304/3 "2010-04-27T13:26:44Z")

</div>

+1

In cases like this, when you can use a string eval, it is usually the  
best approach. There are cases where you cannot do this b/c you need  
access to a local variable.

> **···**
>
> On Apr 27, 8:01 am, Brian Candler \<b.cand...@pobox.com\> wrote:
> 
> > It's pretty reasonable to use eval in the code you provide. I think the  
> > method it defines will be faster because there is no closure created.

---

<div class="post-metadata">

**Author:** ![kevid](https://avatars.discourse-cdn.com/v4/letter/k/e480ec/32.png) [@kevid](https://rubytalk.org/u/kevid)\
**Post date:** [27 April 2010 17:20 UTC](https://rubytalk.org/t/ruby-eval-function/58304/4 "2010-04-27T17:20:08Z")

</div>

Thanks all.

Brian Candle solution just did for me.

Please, not to be asking too much, I need to make use of "Hpricot gem"  
files. I don't want to install it as a gem. I copied lib/hpricot/\*{all  
files} and lib/hpricot.rb to my application.

below is lib/hpricot.rb

begin  
&nbsp;&nbsp;require 'encoding/character/utf-8'  
rescue LoadError  
end

#require 'hpricot\_scan'  
require 'hpricot/tag'  
require 'hpricot/modules'  
require 'hpricot/traverse'  
require 'hpricot/inspect'  
require 'hpricot/parse'  
require 'hpricot/builder'

ALL files loaded properly except "hpricot\_scan". i can't find anything  
like hpricot\_scan.rb in the gem's folder.

Any help is highly appreciated.

---

<div class="post-metadata">

**Author:** ![kevid](https://avatars.discourse-cdn.com/v4/letter/k/e480ec/32.png) [@kevid](https://rubytalk.org/u/kevid)\
**Post date:** [27 April 2010 17:20 UTC](https://rubytalk.org/t/ruby-eval-function/58304/5 "2010-04-27T17:20:11Z")

</div>

Thanks all.

Brian Candle solution just did for me.

Please, not to be asking too much, I need to make use of "Hpricot gem"  
files. I don't want to install it as a gem. I copied lib/hpricot/\*{all  
files} and lib/hpricot.rb to my application.

below is lib/hpricot.rb

begin  
&nbsp;&nbsp;require 'encoding/character/utf-8'  
rescue LoadError  
end

#require 'hpricot\_scan'  
require 'hpricot/tag'  
require 'hpricot/modules'  
require 'hpricot/traverse'  
require 'hpricot/inspect'  
require 'hpricot/parse'  
require 'hpricot/builder'

ALL files loaded properly except "hpricot\_scan". i can't find anything  
like hpricot\_scan.rb in the gem's folder.

Any help is highly appreciated.

---

<div class="post-metadata">

**Author:** ![Roger\_Pack4](https://avatars.discourse-cdn.com/v4/letter/r/bb73d2/32.png) [@Roger\_Pack4](https://rubytalk.org/u/Roger_Pack4)\
**Post date:** [27 April 2010 17:27 UTC](https://rubytalk.org/t/ruby-eval-function/58304/6 "2010-04-27T17:27:20Z")

</div>

> ALL files loaded properly except "hpricot\_scan". i can't find anything  
> like hpricot\_scan.rb in the gem's folder.

doing a  
$ gem which hpricot\_scan

might help you locate it.  
-rp

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![kevid](https://avatars.discourse-cdn.com/v4/letter/k/e480ec/32.png) [@kevid](https://rubytalk.org/u/kevid)\
**Post date:** [27 April 2010 17:55 UTC](https://rubytalk.org/t/ruby-eval-function/58304/7 "2010-04-27T17:55:08Z")

</div>

thanks,

But this provided "hpricot\_scan.so" {i.e /usr/lib/ruby/gems/1.8/gems/  
hpricot-0.8.2/lib/hpricot\_scan.so }

I have added this file but no luck

> **···**
>
> On Apr 27, 6:27 pm, Roger Pack \<rogerpack2...@gmail.com\> wrote:
> 
> > \> ALL files loaded properly except "hpricot\_scan". i can't find anything  
> > \> like hpricot\_scan.rb in the gem's folder.
> > 
> > doing a  
> > $ gem which hpricot\_scan
> > 
> > might help you locate it.  
> > -rp  
> > --  
> > Posted viahttp://www.ruby-forum.com/.

---

<div class="post-metadata">

**Author:** ![Roger\_Pack4](https://avatars.discourse-cdn.com/v4/letter/r/bb73d2/32.png) [@Roger\_Pack4](https://rubytalk.org/u/Roger_Pack4)\
**Post date:** [27 April 2010 19:08 UTC](https://rubytalk.org/t/ruby-eval-function/58304/8 "2010-04-27T19:08:33Z")

</div>

> But this provided "hpricot\_scan.so" {i.e /usr/lib/ruby/gems/1.8/gems/  
> hpricot-0.8.2/lib/hpricot\_scan.so }
> 
> I have added this file but no luck

make sure it's in the load path ($:) or add it explicitly, like 'require  
./hpricot\_scan' or what not.  
-rp

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).
