# Avoiding eval

**URL:** <https://www.ruby-forum.com/t/avoiding-eval/194000>\
**Category:** Ruby\
**Created:** [August 27, 2010, 5:24pm UTC](https://www.ruby-forum.com/t/avoiding-eval/194000 "2010-08-27T17:24:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rawroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/94ad74/32.png) [@rawroe](https://www.ruby-forum.com/u/rawroe)\
**Post date:** [August 27, 2010, 5:24pm UTC](https://www.ruby-forum.com/t/avoiding-eval/194000/1 "2010-08-27T17:24:51Z")

</div>

Hey all,  
If I have a string like “Math”, I know I can use const\_get to turn it  
into  
an instance of Class. Awesome.

But what if I have something like “Math::PI”. Am I stuck using eval to  
resolve that?

---

<div class="post-metadata">

**Author:** ![rawroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/94ad74/32.png) [@rawroe](https://www.ruby-forum.com/u/rawroe)\
**Post date:** [August 27, 2010, 5:40pm UTC](https://www.ruby-forum.com/t/avoiding-eval/194000/2 "2010-08-27T17:40:39Z")

</div>

On 27.08.2010 17:24, Andrew W. wrote:

> If I have a string like “Math”, I know I can use const\_get to turn it into  
> an instance of Class. Awesome.
> 
> But what if I have something like “Math::PI”. Am I stuck using eval to  
> resolve that?

One typical idiom looks like this:

a\_class = str.split(’::’).inject(Object) {|cl,n| cl.const\_get n}

Cheers

robert

---

<div class="post-metadata">

**Author:** ![rawroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/94ad74/32.png) [@rawroe](https://www.ruby-forum.com/u/rawroe)\
**Post date:** [August 27, 2010, 5:49pm UTC](https://www.ruby-forum.com/t/avoiding-eval/194000/3 "2010-08-27T17:49:26Z")

</div>

Well, sure. That’s a good point. But now you’re taking 3 times as long  
as  
eval, instead of 1/5 the time, according to my tests.

On Fri, Aug 27, 2010 at 11:40 AM, Robert K.

---

<div class="post-metadata">

**Author:** ![rawroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/94ad74/32.png) [@rawroe](https://www.ruby-forum.com/u/rawroe)\
**Post date:** [August 27, 2010, 6:26pm UTC](https://www.ruby-forum.com/t/avoiding-eval/194000/4 "2010-08-27T18:26:20Z")

</div>

Err, I think I wasn’t very clear in my last email, so I’ll say it in a  
benchmark this time.

require ‘benchmark’

Benchmark.bm do |b|

b.report “using eval” do  
1\_000\_000.times { eval “Math” }  
end

b.report “using const\_get” do  
1\_000\_000.times { Kernel.const\_get “Math” }

end

b.report “using eval on Math::PI” do  
1\_000\_000.times { eval “Math::Pi” }

end

b.report “using const\_get injection on Math::PI” do  
1\_000\_000.times { “Math::PI”.split("::").inject(Object) { |cl,n|  
cl.const\_get n } }

end

end

using eval 6.5  
using const\_get 1.297  
using eval on Math::Pi 6.875  
using const\_get injection on Math::PI 18.65

Without the performance benefit, it seems like there’s not much benefit  
in  
avoiding eval :(.

---

<div class="post-metadata">

**Author:** ![rawroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/94ad74/32.png) [@rawroe](https://www.ruby-forum.com/u/rawroe)\
**Post date:** [August 28, 2010, 8:40am UTC](https://www.ruby-forum.com/t/avoiding-eval/194000/5 "2010-08-28T08:40:21Z")

</div>

On Fri, Aug 27, 2010 at 10:40 AM, Robert K.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)wrote:

> 

Here is how Rails implements Robert’s suggestion:

(see method constantize)

> <https://github.com/rails/rails/blob/main/activesupport/lib/active_support/inflector/methods.rb>

---

<div class="post-metadata">

**Author:** ![rawroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/94ad74/32.png) [@rawroe](https://www.ruby-forum.com/u/rawroe)\
**Post date:** [August 27, 2010, 6:27pm UTC](https://www.ruby-forum.com/t/avoiding-eval/194000/6 "2010-08-27T18:27:31Z")

</div>

Please do not top post.

On 27.08.2010 17:48, Andrew W. wrote:

> Well, sure. That’s a good point. But now you’re taking 3 times as long as  
> eval, instead of 1/5 the time, according to my tests.

Is it a performance issue? If not, why bother now? The version with  
eval is much less secure plus eval might not work under all  
circumstances with your string (see $SAFE).

Cheers

robert
