# Metaprogammatically define methods

**URL:** <https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322>\
**Category:** Ruby\
**Created:** [November 17, 2006, 4:42pm UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322 "2006-11-17T16:42:35Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 17, 2006, 4:42pm UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/1 "2006-11-17T16:42:35Z")

</div>

I’m writing a harness for some tests that use watir. Rather than having  
to boilerplate code in the definition of each test like  
def test\_1  
load test1  
end

I want to read the testnames in from a file which will be easier for the  
user. What I’d like to do is something along this structure (which I  
adapted from a really good blog in metaprogramming  
[Ruby, Meta-programming, and Watir | Invisible Blocks](http://invisibleblocks.wordpress.com/2006/06/14/ruby-meta-programming-and-watir/)):

testlist = Array.new

File.open(‘readme.txt’, ‘r’) do |eachline|  
while (line = eachline.gets)  
testlist \<\< line  
end  
end  
#puts testlist

testlist.each { |entry|  
code = \<\<METHOD\_TEMPLATE  
def test\_#{entry}()  
puts “testing #{entry}”  
end  
METHOD\_TEMPLATE  
}

and then call each method I’ve defined. However, I’m not sure I’m going  
about this the correct way.

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 17, 2006, 5:58pm UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/2 "2006-11-17T17:58:43Z")

</div>

Hi –

On Sat, 18 Nov 2006, Max R. wrote:

> code = \<\<METHOD\_TEMPLATE  
> def test\_#{entry}()  
> puts “testing #{entry}”  
> end  
> METHOD\_TEMPLATE  
> }
> 
> and then call each method I’ve defined. However, I’m not sure I’m going  
> about this the correct way.

We (Austin Codefest of 2002) did something very like this in the tests  
for Ruby scanf. If you look for test\_scanf.rb in the Ruby source,  
you’ll see it, near the bottom of the file. We used define\_method.  
(I think that was back in the days when I habitually switched the  
order of actual and expected in my assertions, so you have to  
compensate for that 🙂

It’s not exactly the same as yours but I’d say that define\_method is  
your best bet too.

David

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 18, 2006, 8:53am UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/3 "2006-11-18T08:53:07Z")

</div>

Max R. wrote:

> testlist = Array.new
> 
> File.open(‘readme.txt’, ‘r’) do |eachline|  
> while (line = eachline.gets)  
> testlist \<\< line  
> end  
> end  
> #puts testlist

testlist = File.open(‘readme.txt’).readlines

> testlist.each { |entry|  
> code = \<\<METHOD\_TEMPLATE  
> def test\_#{entry}()  
> puts “testing #{entry}”  
> end  
> METHOD\_TEMPLATE  
> }  
> and then call each method I’ve defined. However, I’m not sure I’m going  
> about this the correct way.

Use define\_method whenever possible. The only case where you would put  
code in a string (and then load it using eval) is if your methods need  
to accept a block argument (define\_method does not accept block argument  
until Ruby 1.9).

class Foo  
File.open(‘readme.txt’).readlines.each do |entry|  
define\_method “test\_#{entry}”.to\_sym do  
puts “testing #{entry}”  
end  
end  
end

Foo.new.test\_whatever

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 18, 2006, 8:57am UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/4 "2006-11-18T08:57:09Z")

</div>

Suraj K. wrote:

> class Foo  
> File.open(‘readme.txt’).readlines.each do |entry|

Well it turns out that the above line can be simplified to:

File.open(‘readme.txt’).each\_line do |entry|

or even to:

IO.foreach(‘readme.txt’) do |entry|

Personally, I prefer each\_line because IO.foreach sounds like “for each  
IO object in …” instead of “for each line in …”.

> ```
> define_method "test_#{entry}".to_sym do
> puts "testing #{entry}"
> end
> 
> ```
> 
> end  
> end
> 
> Foo.new.test\_whatever

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 18, 2006, 1:10pm UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/5 "2006-11-18T13:10:30Z")

</div>

Hi –

On Sat, 18 Nov 2006, Suraj K. wrote:

> class Foo  
> File.open(‘readme.txt’).readlines.each do |entry|  
> define\_method “test\_#{entry}”.to\_sym do

You don’t need to\_sym there; define\_method will take a string.

David

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 24, 2006, 11:00am UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/6 "2006-11-24T11:00:02Z")

</div>

Suraj K. wrote:

> Suraj K. wrote:
> 
> > class Foo  
> > File.open(‘readme.txt’).readlines.each do |entry|
> 
> Well it turns out that the above line can be simplified to:
> 
> File.open(‘readme.txt’).each\_line do |entry|
> 
> or even to:
> 
> IO.foreach(‘readme.txt’) do |entry|
> 
> Personally, I prefer each\_line because IO.foreach sounds like “for each  
> IO object in …” instead of “for each line in …”.
> 
> > ```
> > define_method "test_#{entry}".to_sym do
> > puts "testing #{entry}"
> > end
> > 
> > ```
> > 
> > end  
> > end
> > 
> > Foo.new.test\_whatever

Got a bit of help on this one and the solution I’m now going with is:

File.open(‘readme.txt’).each\_line do |entry|  
self.send(:define\_method, entry.strip.to\_sym){ puts “testing  
#{entry}” }  
#self.send(:public, entry.strip.to\_sym )  
end  
end

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 24, 2006, 1:53pm UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/7 "2006-11-24T13:53:49Z")

</div>

Hi –

On Fri, 24 Nov 2006, Max R. wrote:

> Got a bit of help on this one and the solution I’m now going with is:
> 
> File.open(‘readme.txt’).each\_line do |entry|  
> self.send(:define\_method, entry.strip.to\_sym){ puts “testing  
> #{entry}” }  
> #self.send(:public, entry.strip.to\_sym )  
> end  
> end

define\_method takes a string, so you can get rid of “to\_sym”. (Same  
for public in the commented-out line, if you ever use that.)

David

---

<div class="post-metadata">

**Author:** ![shinji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@shinji](https://www.ruby-forum.com/u/shinji)\
**Post date:** [November 20, 2006, 11:41am UTC](https://www.ruby-forum.com/t/metaprogammatically-define-methods/76322/8 "2006-11-20T11:41:31Z")

</div>

> Use define\_method whenever possible. The only case where you would put  
> code in a string (and then load it using eval) is if your methods need  
> to accept a block argument (define\_method does not accept block argument  
> until Ruby 1.9).
> 
> class Foo  
> File.open(‘readme.txt’).readlines.each do |entry|  
> define\_method “test\_#{entry}”.to\_sym do  
> puts “testing #{entry}”  
> end  
> end  
> end
> 
> Foo.new.test\_whatever

I still run into undefined method errors using this format. Are there  
any restrictions on the format the generated method name can take?
