[Design advice] including a file as code ('as is')

dear list,

I have 2 files: main.rb and include_me.rb.
I want include_me.rb to contain only the method definitions
(dont have to care about its module and class).

[[background information:
the real problem is a bit more complicated.
finally 'main.rb' will open lots of different 'include_me.rb's in a loop
and even check if it has already opened them before open them twice, but
running classname.run each time in the loop (i.e. file name of the include
and classname are variables passed to main.rb in the loop)]]

the following code works, but
        - will it always work no matter whats in 'include_me.rb'?
        - is there a better solution to get rid of the evil "eval"?

I know there is send(:define_method, "method_name") but I want
'include_me.rb' to appear like if it would be a valid ruby script on its
own (without using any "special methods" only for the inclusion purpose).

to simply redefine the same class in each include file is not an option.

regards,

benny

####### here comes the pseudo code #########

# main.rb
module My_Module
        class MyTest
                def initialize(str)
                        puts "initializing: #{str}"
                end
                lines = []
                File.open('include_me.rb').each_line{ |line |
                        lines << line
                }
                eval(lines.join(';'))
        end
end

test = My_Module::MyTest.new("new test with sound check")
test.run("sound check", 5)

# include_me.rb
def run(str, t)
        meth2(t)
        puts str
end

def meth2(t)
        t.times do | tm |
                puts "check: #{tm} "
        end
end

Look at Kernel#load; there's a wrap option. When Ruby requires or
loads a file, the code in it is executed -- and then because you can
wrap the loaded file in a module, you can then run it as well.

-austin

···

On Fri, 3 Sep 2004 21:50:46 +0900, Benny <linux@marcrenearns.de> wrote:

I have 2 files: main.rb and include_me.rb. I want include_me.rb to
contain only the method definitions (dont have to care about its
module and class).

[[background information: the real problem is a bit more
complicated. finally 'main.rb' will open lots of different
'include_me.rb's in a loop and even check if it has already opened
them before open them twice, but running classname.run each time
in the loop (i.e. file name of the include and classname are
variables passed to main.rb in the loop)]]

the following code works, but
- will it always work no matter whats in 'include_me.rb'?
- is there a better solution to get rid of the evil "eval"?

I know there is send(:define_method, "method_name") but I want
'include_me.rb' to appear like if it would be a valid ruby script on its
own (without using any "special methods" only for the inclusion purpose).

to simply redefine the same class in each include file is not an option.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca
: as of this email, I have [ 6 ] Gmail invitations

Hi --

dear list,

I have 2 files: main.rb and include_me.rb.
I want include_me.rb to contain only the method definitions
(dont have to care about its module and class).

[[background information:
the real problem is a bit more complicated.
finally 'main.rb' will open lots of different 'include_me.rb's in a loop
and even check if it has already opened them before open them twice, but
running classname.run each time in the loop (i.e. file name of the include
and classname are variables passed to main.rb in the loop)]]

the following code works, but
        - will it always work no matter whats in 'include_me.rb'?
        - is there a better solution to get rid of the evil "eval"?

I know there is send(:define_method, "method_name") but I want
'include_me.rb' to appear like if it would be a valid ruby script on its
own (without using any "special methods" only for the inclusion purpose).

to simply redefine the same class in each include file is not an option.

regards,

benny

####### here comes the pseudo code #########

# main.rb
module My_Module
        class MyTest
                def initialize(str)
                        puts "initializing: #{str}"
                end
                lines =
                File.open('include_me.rb').each_line{ |line |
                        lines << line
                }
                eval(lines.join(';'))

I know you want to avoid eval, but as long as it's here, just to show
you a somewhat shorter way to eval the contents of a file:

   eval(File.read("include_me.rb"))

(Ruby really is good at doing things like that concisely :slight_smile:

Anyway, as for another way: you could just 'require' the file,
although then you end up with the methods being private. But if you
know what they're called that may be not a big problem:

  module MyModule
    class MyTest
      def initialize(str)
        puts "initialize: #{str}"
        require "include_me.rb"
        self.class.class_eval { public :run }
      end
    end
  end

etc.

David

···

On Fri, 3 Sep 2004, Benny wrote:

--
David A. Black
dblack@wobblini.net

Benny wrote:

dear list,

I have 2 files: main.rb and include_me.rb.
I want include_me.rb to contain only the method definitions (dont have to care about its module and class).

[[background information: the real problem is a bit more complicated.
finally 'main.rb' will open lots of different 'include_me.rb's in a loop
and even check if it has already opened them before open them twice, but
running classname.run each time in the loop (i.e. file name of the include
and classname are variables passed to main.rb in the loop)]]

the following code works, but
        - will it always work no matter whats in 'include_me.rb'?
        - is there a better solution to get rid of the evil "eval"?

I know there is send(:define_method, "method_name") but I want
'include_me.rb' to appear like if it would be a valid ruby script on its
own (without using any "special methods" only for the inclusion purpose).

to simply redefine the same class in each include file is not an option.

Take a look at

http://redshift.sourceforge.net/script/

It's a variation on the load-with-wrapper suggestion and it still uses eval, but it returns the module containing all the methods and constants defined at the top-level in the loaded file. You can then call them directly or include the module in some class.

David A. Black wrote:

Anyway, as for another way: you could just 'require' the file,
although then you end up with the methods being private. But if you
know what they're called that may be not a big problem:

no, it won't work in my case:

in the real app 'MyTest' are different classes for each include and all of
them have the same parent class. in this parent class is a method defined to
make a new object of any given 'MyTest'-class (i.e. from another include)
and to invoke a given method of this class. this methods are unknown for
main.rb (execept the one and only "run" method that has to be in the
include). additionally there might be class methods that should be called
this way (without the creation of an object of this class)

benny

Austin Ziegler wrote:

Look at Kernel#load; there's a wrap option. When Ruby requires or
loads a file, the code in it is executed -- and then because you can
wrap the loaded file in a module, you can then run it as well.

that's exactly what a was looking for!!
thanks!

benny

Benny wrote:

Austin Ziegler wrote:

Look at Kernel#load; there's a wrap option. When Ruby requires or
loads a file, the code in it is executed -- and then because you can
wrap the loaded file in a module, you can then run it as well.

that's exactly what a was looking for!!
thanks!

benny

perhaps that was spoken too soon:

I tried it, but I don't get the wrapper-module back. load only returns true
or false, so have an anonymous module and can't do anything with it

my idea was to do this

#### code that doesn't work ####
module My_Module
class MyTest
def initialize(str)
puts "initializing: #{str}"
end
                include load('include_me.rb', true)
end
end

but since load() returns true it won't work.
am I missing something or is load() not the answer for my problem?

benny

"Benny" <linux@marcrenearns.de> schrieb im Newsbeitrag
news:2pr9lsFoodf3U1@uni-berlin.de...

David A. Black wrote:

> Anyway, as for another way: you could just 'require' the file,
> although then you end up with the methods being private. But if you
> know what they're called that may be not a big problem:
no, it won't work in my case:

in the real app 'MyTest' are different classes for each include and all of
them have the same parent class. in this parent class is a method defined

to

make a new object of any given 'MyTest'-class (i.e. from another include)
and to invoke a given method of this class. this methods are unknown for
main.rb (execept the one and only "run" method that has to be in the
include). additionally there might be class methods that should be called
this way (without the creation of an object of this class)

AFAIK there is a solution for this already in RubyUnit. Maybe the simplest
is to just use that.

Kind regards

    robert

... I'm not sure that you can do what you want to do without the
eval() call, then.

-austin