views:

441

answers:

4

I am working on an API that needs to load all of the .rb files in its current directory and all subdirectories. Currently, I am entering a new require statement for each file that I add but I would like to make it where I only have to place the file in one of the subdirectories and have it automatically added.

Is there a standard command to do this?

+4  A: 
require "find"

Find.find(folder) do |file|
  next if File.extname(file) != ".rb"
  puts "loading #{file}"
  load(file)
end

This will recursively load each .rb file.

Geo
+6  A: 

In this case its loading all the files under the lib directory:

Dir["#{File.dirname(__FILE__)}/lib/**/*.rb"].each { |f| load(f) }
Miguel Fonseca
why do you use `load` and not `require`?
johannes
You can use both, but require is usually passed a library name, with no extension, rather than a file name.
Miguel Fonseca
but `require`, doesn't mind if you pass in the extension, so in my opinion it is preferable
johannes
If you use `require`, the file will be treated as a source file and loaded as a library. Using `load` causes the file to be run as a script and will prevent any local variables in the loaded file from being imported into the current environment. Ruby will also let you re-import a file with `load` but not with `require`. Either syntax can be used here, just make sure it is doing what you think it is doing.
bta
A: 
def rLoad(dir)
    Dir.entries(dir).each {|f|
        next if f=='.' or f=='..'
        if File.directory?(f)
            rInclude(f)
        else
            load(f) if File.fnmatch('*.rb', f)
        end
    }
end

This should recursively load all .rb files in the directory specified by dir. For example, rLoad Dir.pwd would work on the current working directory.

Be careful doing this, though. This does a depth-first search and if there are any conflicting definitions in your Ruby scripts, they may be resolved in some non-obvious manner (alphabetical by folder/file name I believe).

bta
Why aren't you matching directly against `f` in your load call?
Geo
If you are referring to the statement `File.fnmatch('*.rb', f)`, the statement returns true if the filename `f` matches the pattern `*.rb`. This ensures that we are only `load`-ing ruby scripts and not any other files that might happen to be in the folder. Note that you may have to add another condition if you also have some scripts that use the .rbw extension.
bta
Yes. But you could have used `load(f) if f =~/\.rb/`. I was referring to why you're using fnmatch over the builtin regex support.
Geo
Ah, I see what you mean now. When I wrote the above code I happened to be working on something else that was using the fnmatch method so that line was pretty much a copy/paste. I suppose `~/\.rb$/` regex would work as well (added the `$` to prevent matching files like "script.rb.bak").
bta
A: 

You should have a look at this gem. It is quite small so you can actually re-use the code instead of installing the whole gem.

Waseem
The link is broken.
juan2raid
http://github.com/mlightner/require_directory this should work.
Waseem