# How do Rakefiles "know" about built-in Rake methods?

**URL:** <https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304>\
**Category:** Ruby\
**Created:** [February 2, 2007, 11:06pm UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304 "2007-02-02T23:06:31Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@jeff](https://www.ruby-forum.com/u/jeff)\
**Post date:** [February 2, 2007, 11:06pm UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304/1 "2007-02-02T23:06:31Z")

</div>

I’m looking into a way to let business users write functional tests in  
rails, and I wanted to have my functional test file load an external  
file to supply the body of a method. It occurs to me that Rake must  
have solved a similar problem, but I can’t quite figure out how Jim  
did it.

What I want to write is something like this:

class MyTests \< Test::Unit::TestCase

# typical setup and teardown here

# a test method to “wrap” an external ruby file

def test\_acceptance  
load ‘acceptance.rb’ # load file written by business user  
end

def foo  
end

def bar  
end

end

I admit it didn’t look right when I wrote it. I had hoped that the  
code in acceptance.rb could be bare Ruby code. in other words, it  
would look like and feel top-level Ruby, but could call foo and bar  
because it’s really in the midst of the test\_acceptance method.

So I conclude that load() starts a new scope. I guess I could add my  
methods to Object and/or Module to get them to be seen by the external  
file, but I don’t think that does any good either.

But Rake does something similar, right? I think it defines the task()  
method, etc. and you can refer to them in “bare” ruby code in your  
rake file.

What glue is being used in Rake that I’m missing?

Thanks!  
Jeff

---

<div class="post-metadata">

**Author:** ![jeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@jeff](https://www.ruby-forum.com/u/jeff)\
**Post date:** [February 2, 2007, 11:53pm UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304/2 "2007-02-02T23:53:36Z")

</div>

On 2/2/07, Jeff [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> # typical setup and teardown here
> 
> def bar  
> methods to Object and/or Module to get them to be seen by the external  
> file, but I don’t think that does any good either.
> 
> But Rake does something similar, right? I think it defines the task()  
> method, etc. and you can refer to them in “bare” ruby code in your  
> rake file.
> 
> What glue is being used in Rake that I’m missing?

Jim defined the basic rake methods [task, rule, file, directory, …]  
in the global ruby context – much the same way you would define a  
method in an irb session. When your Rakefile is loaded by the rake  
system, it automatically has access to all these rake methods. Both  
exist in the same global context.

Your code above is defining instance methods (foo and bar) within a  
class. When you load a file in your test\_acceptance method, that file  
is being loaded in the global context NOT in the context of your test  
case instance.

To do the latter …

def test\_acceptance  
self.instance\_eval IO.readlines(‘acceptance.rb’)  
end

A simpler example …

ary = Array.new  
ary.instance\_eval “length” #=\> 0

Hope this helps.

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![jeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@jeff](https://www.ruby-forum.com/u/jeff)\
**Post date:** [February 3, 2007, 12:02am UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304/3 "2007-02-03T00:02:37Z")

</div>

Jeff wrote:

> # typical setup and teardown here
> 
> def bar  
> methods to Object and/or Module to get them to be seen by the external

The task method is defined by Rake at the top level, i.e. a normal  
method not within the scope of a class

def task(args, &block)  
Rake::Task.define\_task(args, &block)  
end

Method defined in the top level context are available globally, which is  
why you can require ‘rake’ and then use the task method.

---

<div class="post-metadata">

**Author:** ![jeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@jeff](https://www.ruby-forum.com/u/jeff)\
**Post date:** [February 3, 2007, 1:42am UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304/4 "2007-02-03T01:42:44Z")

</div>

On Sat, 2007-02-03 at 07:05 +0900, Jeff wrote:

> # typical setup and teardown here
> 
> def bar  
> methods to Object and/or Module to get them to be seen by the external  
> file, but I don’t think that does any good either.
> 
> But Rake does something similar, right? I think it defines the task()  
> method, etc. and you can refer to them in “bare” ruby code in your  
> rake file.
> 
> What glue is being used in Rake that I’m missing?
> 
> Thanks!  
> Jeff

I think I get your point. This is what I’d do, though:

module TestContainer  
class \<\< self  
def tests  
@tests ||= {}  
end

```
  def define_test(name, &body)
    @tests[name] = body
  end
end

```

end

module Kernel  
def test(name, &body)  
TestContainer.define\_test(name, &body)  
end  
end

Then you can just go and do:

# foo\_test.rb

test :foo do  
assert\_equal 4, 2 \* 2  
end

And then, in your test file:

require ‘foo\_test’

class MyTest \< Test::Unit::TestCase  
TestContainer.tests.each do |name, body|  
define\_method(“test\_#{name}”, &body)  
end  
end

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![jeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@jeff](https://www.ruby-forum.com/u/jeff)\
**Post date:** [February 3, 2007, 1:59am UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304/5 "2007-02-03T01:59:45Z")

</div>

On 2/2/07, Jeff [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def bar  
> end
> 
> end

Systir was made to solve this exact problem. Have a look, it’s not a  
lot of  
code and should be easy to adapt to your situation.

[http://atomicobject.com/pages/System+Testing+in+Ruby](http://atomicobject.com/pages/System+Testing+in+Ruby)

Cheers,  
/Nick

---

<div class="post-metadata">

**Author:** ![jeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@jeff](https://www.ruby-forum.com/u/jeff)\
**Post date:** [February 3, 2007, 6:05am UTC](https://www.ruby-forum.com/t/how-do-rakefiles-know-about-built-in-rake-methods/84304/6 "2007-02-03T06:05:59Z")

</div>

Wow, thanks everyone for all the help… I’ve got a lot to investigate  
now.

Jeff
