Load a Ruby source with params


#1

Hello, Ruby world,

Do you know how loading a Ruby source with parameters? I had try so by
using:
load(my_file my_arg)

but it do not seems to work…

Thank you.


#2

Sai Hl wrote:

Do you know how loading a Ruby source with parameters? I had try so by
using:
load(my_file my_arg)

but it do not seems to work…

I think you’re confusing two things.

(1) Loading in more Ruby code to the currently-running Ruby interpreter.
This is done using “load” or “require”. There is no concept of
“parameters” here. However you could set a global variable (e.g. $foo)
or a constant (Foo), which the code in the other file makes use of.

But it would be more normal for the other file just to define modules or
classes, and then after the load has completed you invoke one of those
modules or classes, at which point you can pass whatever parameters you
like.

(2) Forking and execing a new child process. This could be another
Ruby interpreter, but it could also be any other program on your system.
When you do this, you can pass command-line arguments (and/or
environment variables and open files)

The simplest way is with Kernel#system, e.g.

system("/bin/prog","arg1","arg2")

but other options include backticks, IO.popen, the open3 and open4
libraries, and the low-level Kernel#fork and Kernel#exec calls.


#3

Brian C. wrote:

(1) Loading in more Ruby code to the currently-running Ruby interpreter.
This is done using “load” or “require”. There is no concept of
“parameters” here. However you could set a global variable (e.g. $foo)
or a constant (Foo), which the code in the other file makes use of.

But it would be more normal for the other file just to define modules or
classes, and then after the load has completed you invoke one of those
modules or classes, at which point you can pass whatever parameters you
like.

(2) Forking and execing a new child process. This could be another
Ruby interpreter, but it could also be any other program on your system.
When you do this, you can pass command-line arguments (and/or
environment variables and open files)

The simplest way is with Kernel#system, e.g.

system("/bin/prog","arg1","arg2")

but other options include backticks, IO.popen, the open3 and open4
libraries, and the low-level Kernel#fork and Kernel#exec calls.

Many thanks for your detailled answer, Brian C…

until now I used those few lines:

inc.test.rb

'Hello ’ + subject

inc.other_test.rb

'Hi, ’ + subject

main.rb

@files = []
subject = ‘World’
Dir[‘inc.*.rb’].each do |file|
open(file) { |f| @files << f.read }
end
@files.each { |f| puts “#{eval(f)}” }

But it’s true that the eval function takes a lot of ressources and the
(1) solution is better, using global variables.

I am going to try to use the (2) solutions, with a module for any files
like:

inc.test.rb

module Inc
def say
‘Hello’ + subject
end
end

But is this possible in my case, because I don’t know the name of each
module (which is depend of the name of its file)?

Regards


#4

Sai Hl wrote:

I am going to try to use the (2) solutions, with a module for any files
like:

inc.test.rb

module Inc
def say
‘Hello’ + subject
end
end

But is this possible in my case, because I don’t know the name of each
module (which is depend of the name of its file)?

If you are consistent in your naming, you can map the filename to the
module name (or vice versa). For example, look at the underscore and
camelize methods of ActiveSupport from Rails. These just convert FooBar"
to “foo_bar”, and vice versa.

Then you can use const_get to convert the name “FooBar” to the actual
module instance on which to invoke the method. e.g.

puts Object.const_get(“Inc”).say(subject)

A simpler solution is just to iterate over all the modules within an
enclosing module/namespace:

==> inc1.rb <==
module Extensions
module Inc1
def self.say(subject)
“Hello #{subject}”
end
end
end

==> inc2.rb <==
module Extensions
module Inc2
def self.say(subject)
“Goodbye #{subject}”
end
end
end

==> main.rb <==
Dir[“inc*.rb”].each { |src| load src }
Extensions.constants.each do |k|
puts Extensions.const_get(k).say(“world”)
end

Aside: if you strip off the .rb extension (look at File.basename) then
you can use ‘require’ instead of ‘load’. This prevents loading the same
file multiple times.


#5

Cyril Beer wrote:

Do you know how loading a Ruby source with parameters? I had try so by
using:
load(my_file my_arg)

It’s a bit awkward, but there’s a way to do it with my script library:

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

Quoting the docs:

An “input” can be passed to the script before loading. Simply call
Script.new (or Script.load) with a block. The block is passed a single
argument, the Script module, and executed before the files are loaded
into the Script’s scope. Setting a constant in this block makes the
constant available to the script during loading. For example:
script = Script.load(“my-script.rb”) { |script| script::INPUT = 3 }

The file “my-script.rb” would simply refer to INPUT. You can pass any
number of args this way. See the “program2.rb” in the examples/ dir for
an example.

As a bonus, everything defined in “my-script.rb” is wrapped in a module,
returned by Script.load, and (in the case above) stored in a local
variable in the main file, which you can use to access the constants and
methods defined in my-script.rb.

HTH.


#6

Sai Hl wrote:

(2) Forking and execing a new child process. This could be another
Ruby interpreter, but it could also be any other program on your system.
When you do this, you can pass command-line arguments (and/or
environment variables and open files)

I am going to try to use the (2) solutions

Out of curiosity, why wouldn’t you just define a function in the “other”
file, then call it with whatever arguments you want? This is the second
paragraph of (1).


#7

Thank you, Brian C.!
Your help was very helpful. You should be a great teacher!

Regards.


#8

Very late to the party, but thought I’add this:

If the file you’re loading is designed to handle command-line
parameters, you can just fill the ARGV array before loading:

ARGV[0] = my_arg
load(my_file)   # my_file can then access my_arg as ARGV[0]