Load a Ruby source with params

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.

···

--
Posted via http://www.ruby-forum.com/.

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.

···

--
Posted via http://www.ruby-forum.com/\.

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.

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Brian Candler 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 Candler.

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

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

--
Posted via http://www.ruby-forum.com/\.

Sai Hl wrote:

Brian Candler 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)

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).

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

Regards.

···

--
Posted via http://www.ruby-forum.com/.