views:

100

answers:

4

I'm trying to create an application that will primarily consist of ruby scripts that will be run from the command-line (cron, specifically). I want to have a libs folder, so I can put encapsulated, reusable classes/modules in there, and be able to access them from any script.

I want to be able to put my scripts into a "bin" folder.

What is the best way to give them access to the libs folder? I know I can add to the load path via command-line argument, or at the top of each command-line script. In PHP, it sometimes made more sense to create a custom .ini file and point the cli to the ini file, so you got them all in one pop.

Anything similar for ruby? Based on your experience, what's the best way to go here?

+2  A: 

At the top of each bin/executable, you can put this at the top

#!/usr/bin/env ruby

$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')
require 'libfile'

[etc.]

Were you looking for something different?

If you turn your application into a Ruby gem and install the gem on your system, you don't even need to put this stuff at the top. The require statement would suffice in that case.

dan
No that works great. I'm just wondering if there is a better way.
Sean Clark Hess
If you turn your application into a Ruby gem and install the gem on your system, you don't even need to put this stuff at the top. The `require` statement would suffice in that case.
dan
If you "turn it into a gem" is it still easily editable? I don't want to have to re-export or anything if I make changes.
Sean Clark Hess
Right, in that case, you probably don't want to go the gem route. I don't normally do that either. I use the above technique a lot.
dan
RUBYLIB environment variable! Just what I was looking for
Sean Clark Hess
+1  A: 

If you want to use your classes/modules globally, why not just move them to your main Ruby lib directory? eg: /usr/lib/ruby/1.8/ ?

Eg:

$ cat > /usr/lib/ruby/1.8/mymodule.rb
module HelloWorld
    def hello
        puts("Hello, World!");
    end
end

We have our module in the main lib directory - should be able to require it from anywhere in the system now.

$ irb
irb(main):001:0> require 'mymodule'
=> true
irb(main):002:0> include HelloWorld
=> Object
irb(main):003:0> hello
Hello, World!
=> nil
Is there a way to add a custom directory to your ruby path by exporting some environment variable or something, rather than doing it at the top of a script?
Sean Clark Hess
... and by the above I mean, I want to add a directory to the load_path, not automatically require stuff
Sean Clark Hess
All this talk about rolling your own Ruby made me want to give it ago. So I did. http://frabble.org/myruby.tar.gz - I've called it MyRuby: Original eh? Anyways, it works the same as normal ruby except for one difference. You can set an environment variable RUBY_LOAD_PATH to the directory of your choice and MyRuby will automagically add it to $LOAD_PATH for you so you can use your own libs globally. It only works for one directory at the moment, but I may change that if I decide to go any further with it.Feel free to check it out and let me know what you think.Cheers
oh, forgot to tell you. It's written in C and not ruby, so you shouldn't even need Ruby installed to run it.
That... is awesome. There has GOT to be an easier way though. Gems manipulate the load path somehow, so I'm sure it's possible
Sean Clark Hess
You could use #!/usr/bin/ruby -I/path/to/lib/folder at the top of your script.. or run ruby as 'ruby -I/path/to/lib/folder <source>'
+1  A: 

Sean,

There is no way to not have to require a library, that I know of. I guess if you want to personalize your Ruby so much you could "roll your own" using eval. The script below basically works as the interpreter. You can add your own functions and include libraries. Give the file executable permissions and put it in /usr/bin if you really want. Then just use

$ myruby <source>

Here's the code for a very minimal one. As an example I've included the md5 digest library and created a custom function called md5()

#!/usr/bin/ruby -w

require 'digest/md5';

def executeCode(file)
    handle = File.open(file,'r');
    for line in handle.readlines()
        line = line.strip();
        begin
            eval(line);
        rescue Exception => e
            print "Problem with script '" + file + "'\n";
            print e + "\n";
        end
    end
end

def checkFile(file)
    if !File.exists?(file)
        print "No such source file '" + file + "'\n";
        exit(1);
    elsif !File.readable?(file)
        print "Cannot read from source file '" + file + "'\n";
        exit(1);
    else
        executeCode(file);
    end
end

# My custom function for our "interpreter"
def md5(key=nil)
    if key.nil?
        raise "md5 requires 1 parameter, 0 given!\n";
    else
        return Digest::MD5.hexdigest(key)
    end
end

if ARGV[0].nil?
    print "No input file specified!\n"
    exit(1);
else
    checkFile(ARGV[0]);
end

Save that as myruby or myruby.rb and give it executable permissions (755). Now you're ready to create a normal ruby source file

puts "I will now generate a md5 digest for mypass using the md5() function"
puts md5('mypass')

Save that and run it as you would a normal ruby script but with our new interpreter. You'll notice I didn't need to include any libraries or write the function in the source code because it's all defined in our interpreter.

It's probably not the most ideal method, but it's the only one I can come up with.

Cheers

I'm sorry if I was misleading. I'm fine with the require part, but I want to not have to use "../". I would like to be able to modify the load path without having to do it at the top of each script
Sean Clark Hess
But, seriously, that's hardcore stuff. Thanks, I'm sure it will be useful
Sean Clark Hess
Oh, haha.. sorry for mis-understanding. Ruby uses the $LOAD_PATH variable to search for its libraries. The only way to manipulate this is in the script itself, unless you modify the Ruby source code :-PIf you happen to find a way do let me know!
ruby -e 'puts $LOAD_PATH' will give you all the default library directories. To use your library globally without any extra typing you'd really need to put it in one of them folders.
A: 

There is a RUBYLIB environment variable that can be set to any folder on the system

Sean Clark Hess