require_all 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,13 +1,20 @@
1
- 1.1.0:
2
-
3
- * Add require_rel (require_all relative to the current file)
4
- * Fix bug in auto-appending .rb ala require
5
-
6
- 1.0.1:
7
-
8
- * Allow require_all to take a directory name as an argument
9
-
10
- 1.0.0:
11
-
12
- * Initial release (was originally load_glob, converted to require_all which is
13
- a lot cooler, seriously trust me)
1
+ 1.2.0:
2
+
3
+ * Add load_all, and load_rel which behave similarly to require_all/require_rel except that Kernel#load is used
4
+ * Add autoload_all and autoload_rel (see README and/or specs for examples of usage)
5
+ * Minor bug fixes
6
+ * Improved specs
7
+
8
+ 1.1.0:
9
+
10
+ * Add require_rel (require_all relative to the current file)
11
+ * Fix bug in auto-appending .rb ala require
12
+
13
+ 1.0.1:
14
+
15
+ * Allow require_all to take a directory name as an argument
16
+
17
+ 1.0.0:
18
+
19
+ * Initial release (was originally load_glob, converted to require_all which is
20
+ a lot cooler, seriously trust me)
data/LICENSE CHANGED
@@ -1,58 +1,58 @@
1
- Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
- You can redistribute it and/or modify it under either the terms of the GPL
3
- (see COPYING.txt file), or the conditions below:
4
-
5
- 1. You may make and give away verbatim copies of the source form of the
6
- software without restriction, provided that you duplicate all of the
7
- original copyright notices and associated disclaimers.
8
-
9
- 2. You may modify your copy of the software in any way, provided that
10
- you do at least ONE of the following:
11
-
12
- a) place your modifications in the Public Domain or otherwise
13
- make them Freely Available, such as by posting said
14
- modifications to Usenet or an equivalent medium, or by allowing
15
- the author to include your modifications in the software.
16
-
17
- b) use the modified software only within your corporation or
18
- organization.
19
-
20
- c) rename any non-standard executables so the names do not conflict
21
- with standard executables, which must also be provided.
22
-
23
- d) make other distribution arrangements with the author.
24
-
25
- 3. You may distribute the software in object code or executable
26
- form, provided that you do at least ONE of the following:
27
-
28
- a) distribute the executables and library files of the software,
29
- together with instructions (in the manual page or equivalent)
30
- on where to get the original distribution.
31
-
32
- b) accompany the distribution with the machine-readable source of
33
- the software.
34
-
35
- c) give non-standard executables non-standard names, with
36
- instructions on where to get the original software distribution.
37
-
38
- d) make other distribution arrangements with the author.
39
-
40
- 4. You may modify and include the part of the software into any other
41
- software (possibly commercial). But some files in the distribution
42
- are not written by the author, so that they are not under this terms.
43
-
44
- They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
- files under the ./missing directory. See each file for the copying
46
- condition.
47
-
48
- 5. The scripts and library files supplied as input to or produced as
49
- output from the software do not automatically fall under the
50
- copyright of the software, but belong to whomever generated them,
51
- and may be sold commercially, and may be aggregated with this
52
- software.
53
-
54
- 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
- PURPOSE.
58
-
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see COPYING.txt file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
58
+
data/README.textile CHANGED
@@ -1,83 +1,129 @@
1
- h1. require_all
2
-
3
- A wonderfully simple way to load your code.
4
-
5
- Tired of futzing around with require statements everywhere, littering your code
6
- with <code>require File.dirname(__FILE__)</code> crap? What if you could just
7
- point something at a big directory full of code and have everything just
8
- automagically load regardless of the dependency structure?
9
-
10
- Wouldn't that be nice? Well, now you can!
11
-
12
- <code>require 'require_all'</code>
13
-
14
- You can use require_all in a multitude of different ways.
15
-
16
- The easiest way to use require_all is to just point it at a directory
17
- containing a bunch of .rb files:
18
-
19
- <code>require_all 'lib'</code>
20
-
21
- This will find all the .rb files under the lib directory (including all
22
- subdirectories as well) and load them.
23
-
24
- The proper order to in which to load them is determined automatically. If the
25
- dependencies between the matched files are unresolvable, it will throw the
26
- first unresolvable NameError.
27
-
28
- You can also give it a glob, which will enumerate all the matching files:
29
-
30
- <code>require_all 'lib/**/*.rb'</code>
31
-
32
- It will also accept an array of files:
33
-
34
- <code>require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file? f }</code>
35
-
36
- Or if you want, just list the files directly as arguments:
37
-
38
- <code>require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb'</code>
39
-
40
- Still have the require File.dirname(__FILE__) blues? The require_all gem also
41
- provides a require_rel statement which requires files to relative to the
42
- current file. So you can replace statements like:
43
-
44
- <code>require File.dirname(__FILE__) + '/foobar'</code>
45
-
46
- with just a simple require_rel:
47
-
48
- <code>require_rel 'foobar'</code>
49
-
50
- Even better, require_rel still has the full power of require_all, so you can
51
- use require_rel to load entire directories of code too. If "foobar" is a
52
- directory this will load all the .rb files found under that directory with
53
- automagic dependency handling.
54
-
55
- It's just that easy! Code loading shouldn't be hard.
56
-
57
- h2. Methodology
58
-
59
- I didn't invent the approach this gem uses. It was shamelessly stolen from
60
- Merb (which apparently stole it from elsewhere). Here's how it works:
61
-
62
- # Enumerate the files to be loaded
63
- # Try to load all of the files. If we encounter a NameError loading a
64
- particular file, store that file in a "try to load it later" list.
65
- # If all the files loaded, great, we're done! If not, go through the
66
- "try to load it later" list again rescuing NameErrors the same way.
67
- # If we walk the whole "try to load it later" list and it doesn't shrink
68
- at all, we've encountered an unresolvable dependency. In this case,
69
- require_all will rethrow the first NameError it encountered.
70
-
71
- h2. Questions? Comments? Concerns?
72
-
73
- You can reach the author on github or freenode: "tarcieri"
74
-
75
- Or by email: "tony@medioh.com":mailto:tony@medioh.com
76
-
77
- Got issues with require_all to report? Post 'em here:
78
-
79
- "Github Tracker":http://github.com/tarcieri/require_all/issues
80
-
81
- h2. License
82
-
83
- MIT (see the LICENSE file for details)
1
+ h1. require_all
2
+
3
+ A wonderfully simple way to load your code.
4
+
5
+ Tired of futzing around with require statements everywhere, littering your code
6
+ with <code>require File.dirname(__FILE__)</code> crap? What if you could just
7
+ point something at a big directory full of code and have everything just
8
+ automagically load regardless of the dependency structure?
9
+
10
+ Wouldn't that be nice? Well, now you can!
11
+
12
+ <code>require 'require_all'</code>
13
+
14
+ You can use require_all in a multitude of different ways.
15
+
16
+ The easiest way to use require_all is to just point it at a directory
17
+ containing a bunch of .rb files:
18
+
19
+ <code>require_all 'lib'</code>
20
+
21
+ This will find all the .rb files under the lib directory (including all
22
+ subdirectories as well) and load them.
23
+
24
+ The proper order to in which to load them is determined automatically. If the
25
+ dependencies between the matched files are unresolvable, it will throw the
26
+ first unresolvable NameError.
27
+
28
+ You can also give it a glob, which will enumerate all the matching files:
29
+
30
+ <code>require_all 'lib/**/*.rb'</code>
31
+
32
+ It will also accept an array of files:
33
+
34
+ <code>require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file? f }</code>
35
+
36
+ Or if you want, just list the files directly as arguments:
37
+
38
+ <code>require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb'</code>
39
+
40
+ Still have the require File.dirname(__FILE__) blues? The require_all gem also
41
+ provides a require_rel statement which requires files to relative to the
42
+ current file. So you can replace statements like:
43
+
44
+ <code>require File.dirname(__FILE__) + '/foobar'</code>
45
+
46
+ with just a simple require_rel:
47
+
48
+ <code>require_rel 'foobar'</code>
49
+
50
+ Even better, require_rel still has the full power of require_all, so you can
51
+ use require_rel to load entire directories of code too. If "foobar" is a
52
+ directory this will load all the .rb files found under that directory with
53
+ automagic dependency handling.
54
+
55
+ Also load_all and load_rel methods exist to use Kernel#load instead of Kernel#require!
56
+
57
+ It's just that easy! Code loading shouldn't be hard.
58
+
59
+ h2. autoload_all
60
+
61
+ There's also a methods for performing autoloading - what a bargain!
62
+ Similar syntax is used as for require and load methods although some things have to be
63
+ kept in mind:
64
+
65
+ * Directory and file names have to reflect namespaces and/or constant names - e.g.
66
+ a file called my_file.rb in directories dir1/dir2 has to be defined like this:
67
+ <pre>
68
+ <code>
69
+ module Dir1
70
+ module Dir2
71
+ class MyFile
72
+ end
73
+ end
74
+ end
75
+ </code>
76
+ </pre>
77
+
78
+ in a loader.rb, which is in a parent directory for dir1:
79
+ <code>autoload_all File.dirname(__FILE__) + "/dir1"</code>
80
+
81
+ * A :base_dir option has to be specified if loading directories or files from some other location
82
+ than top-level directory.
83
+
84
+ in dir1/other_file.rb:
85
+ <pre>
86
+ <code>
87
+ autoload_all File.dirname(__FILE__) + "/dir2/my_file.rb",
88
+ :base_dir => File.dirname(__FILE__) + "/../dir1" # top-level namespace starts from dir1
89
+ </code>
90
+ </pre>
91
+
92
+ * All namespaces will be created dynamically by autoload_all - this means that defined?(Dir1) will
93
+ return "constant" even if my_file.rb is not loaded!
94
+
95
+ Of course there's also an autoload_rel method:
96
+ <code>autoload_rel "dir2/my_file.rb", :base_dir => File.dirname(__FILE__) + "/../dir1"</code>
97
+
98
+ If having some problems with autoload_all or autoload_rel then set $DEBUG to true to see how files
99
+ are mapped to their respective modules and classes.
100
+
101
+ h2. Methodology
102
+
103
+ I didn't invent the approach this gem uses. It was shamelessly stolen from
104
+ Merb (which apparently stole it from elsewhere). Here's how it works:
105
+
106
+ # Enumerate the files to be loaded
107
+ # Try to load all of the files. If we encounter a NameError loading a
108
+ particular file, store that file in a "try to load it later" list.
109
+ # If all the files loaded, great, we're done! If not, go through the
110
+ "try to load it later" list again rescuing NameErrors the same way.
111
+ # If we walk the whole "try to load it later" list and it doesn't shrink
112
+ at all, we've encountered an unresolvable dependency. In this case,
113
+ require_all will rethrow the first NameError it encountered.
114
+
115
+ h2. Questions? Comments? Concerns?
116
+
117
+ You can reach the author on github or freenode: "jarm0"
118
+
119
+ Or by email: "jarmo.p@gmail.com":mailto:jarmo.p@gmail.com
120
+
121
+ Got issues with require_all to report? Post 'em here:
122
+
123
+ "Github Tracker":http://github.com/jarmo/require_all/issues
124
+
125
+ h2. License
126
+
127
+ require_all was done originally by Tony Arcieri who asked me to maintain the gem.
128
+
129
+ MIT (see the LICENSE file for details)
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
- require 'rake'
2
- require 'rake/clean'
3
-
4
- Dir['tasks/**/*.rake'].each { |task| load task }
5
-
6
- task :default => :spec
7
-
8
- task :clean do
9
- %w[pkg coverage].each do |dir|
10
- rm_rf dir
11
- end
1
+ require 'rake'
2
+ require 'rake/clean'
3
+
4
+ Dir['tasks/**/*.rake'].each { |task| load task }
5
+
6
+ task :default => :spec
7
+
8
+ task :clean do
9
+ %w[pkg coverage].each do |dir|
10
+ rm_rf dir
11
+ end
12
12
  end
data/lib/require_all.rb CHANGED
@@ -1,125 +1,277 @@
1
- #--
2
- # Copyright (C)2009 Tony Arcieri
3
- # You can redistribute this under the terms of the MIT license
4
- # See file LICENSE for details
5
- #++
6
-
7
- module RequireAll
8
- # A wonderfully simple way to load your code.
9
- #
10
- # The easiest way to use require_all is to just point it at a directory
11
- # containing a bunch of .rb files. These files can be nested under
12
- # subdirectories as well:
13
- #
14
- # require_all 'lib'
15
- #
16
- # This will find all the .rb files under the lib directory and load them.
17
- # The proper order to load them in will be determined automatically.
18
- #
19
- # If the dependencies between the matched files are unresolvable, it will
20
- # throw the first unresolvable NameError.
21
- #
22
- # You can also give it a glob, which will enumerate all the matching files:
23
- #
24
- # require_all 'lib/**/*.rb'
25
- #
26
- # It will also accept an array of files:
27
- #
28
- # require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file(f) }
29
- #
30
- # Or if you want, just list the files directly as arguments:
31
- #
32
- # require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb'
33
- #
34
- def require_all(*args)
35
- # Handle passing an array as an argument
36
- args = args.flatten
37
-
38
- if args.size > 1
39
- # If we got a list, those be are files!
40
- files = args
41
- else
42
- arg = args.first
43
- begin
44
- # Try assuming we're doing plain ol' require compat
45
- stat = File.stat(arg)
46
-
47
- if stat.file?
48
- files = [arg]
49
- elsif stat.directory?
50
- files = Dir.glob File.join(arg, '**', '*.rb')
51
- else
52
- raise ArgumentError, "#{arg} isn't a file or directory"
53
- end
54
- rescue Errno::ENOENT
55
- # If the stat failed, maybe we have a glob!
56
- files = Dir.glob arg
57
-
58
- # Maybe it's an .rb file and the .rb was omitted
59
- if File.file?(arg + '.rb')
60
- require(arg + '.rb')
61
- return true
62
- end
63
-
64
- # If we ain't got no files, the glob failed
65
- raise LoadError, "no such file to load -- #{arg}" if files.empty?
66
- end
67
- end
68
-
69
- files.map! { |file| File.expand_path file }
70
-
71
- begin
72
- failed = []
73
- first_name_error = nil
74
-
75
- # Attempt to load each file, rescuing which ones raise NameError for
76
- # undefined constants. Keep trying to successively reload files that
77
- # previously caused NameErrors until they've all been loaded or no new
78
- # files can be loaded, indicating unresolvable dependencies.
79
- files.each do |file|
80
- begin
81
- require file
82
- rescue NameError => ex
83
- failed << file
84
- first_name_error ||= ex
85
- rescue ArgumentError => ex
86
- # Work around ActiveSuport freaking out... *sigh*
87
- #
88
- # ActiveSupport sometimes throws these exceptions and I really
89
- # have no idea why. Code loading will work successfully if these
90
- # exceptions are swallowed, although I've run into strange
91
- # nondeterministic behaviors with constants mysteriously vanishing.
92
- # I've gone spelunking through dependencies.rb looking for what
93
- # exactly is going on, but all I ended up doing was making my eyes
94
- # bleed.
95
- #
96
- # FIXME: If you can understand ActiveSupport's dependencies.rb
97
- # better than I do I would *love* to find a better solution
98
- raise unless ex.message["is not missing constant"]
99
-
100
- STDERR.puts "Warning: require_all swallowed ActiveSupport 'is not missing constant' error"
101
- STDERR.puts ex.backtrace[0..9]
102
- end
103
- end
104
-
105
- # If this pass didn't resolve any NameErrors, we've hit an unresolvable
106
- # dependency, so raise one of the exceptions we encountered.
107
- if failed.size == files.size
108
- raise first_name_error
109
- else
110
- files = failed
111
- end
112
- end until failed.empty?
113
-
114
- true
115
- end
116
-
117
- # Works like require_all, but paths are relative to the caller rather than
118
- # the current working directory
119
- def require_rel(path)
120
- source_directory = File.dirname caller.first.sub(/:\d+$/, '')
121
- require_all File.join(source_directory, path)
122
- end
123
- end
124
-
125
- include RequireAll
1
+ #--
2
+ # Copyright (C)2009 Tony Arcieri
3
+ # You can redistribute this under the terms of the MIT license
4
+ # See file LICENSE for details
5
+ #++
6
+
7
+ module RequireAll
8
+ # A wonderfully simple way to load your code.
9
+ #
10
+ # The easiest way to use require_all is to just point it at a directory
11
+ # containing a bunch of .rb files. These files can be nested under
12
+ # subdirectories as well:
13
+ #
14
+ # require_all 'lib'
15
+ #
16
+ # This will find all the .rb files under the lib directory and load them.
17
+ # The proper order to load them in will be determined automatically.
18
+ #
19
+ # If the dependencies between the matched files are unresolvable, it will
20
+ # throw the first unresolvable NameError.
21
+ #
22
+ # You can also give it a glob, which will enumerate all the matching files:
23
+ #
24
+ # require_all 'lib/**/*.rb'
25
+ #
26
+ # It will also accept an array of files:
27
+ #
28
+ # require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file(f) }
29
+ #
30
+ # Or if you want, just list the files directly as arguments:
31
+ #
32
+ # require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb'
33
+ #
34
+ def require_all(*args)
35
+ # Handle passing an array as an argument
36
+ args.flatten!
37
+
38
+ options = {:method => :require}
39
+ options.merge!(args.pop) if args.last.is_a?(Hash)
40
+
41
+ if args.empty?
42
+ puts "no files were loaded due to an empty Array" if $DEBUG
43
+ return false
44
+ end
45
+
46
+ if args.size > 1
47
+ # Expand files below directories
48
+ files = args.map do |path|
49
+ if File.directory? path
50
+ Dir[File.join(path, '**', '*.rb')]
51
+ else
52
+ path
53
+ end
54
+ end.flatten
55
+ else
56
+ arg = args.first
57
+ begin
58
+ # Try assuming we're doing plain ol' require compat
59
+ stat = File.stat(arg)
60
+
61
+ if stat.file?
62
+ files = [arg]
63
+ elsif stat.directory?
64
+ files = Dir.glob File.join(arg, '**', '*.rb')
65
+ else
66
+ raise ArgumentError, "#{arg} isn't a file or directory"
67
+ end
68
+ rescue SystemCallError
69
+ # If the stat failed, maybe we have a glob!
70
+ files = Dir.glob arg
71
+
72
+ # Maybe it's an .rb file and the .rb was omitted
73
+ if File.file?(arg + '.rb')
74
+ file = arg + '.rb'
75
+ options[:method] != :autoload ? Kernel.send(options[:method], file) : __autoload(file, file, options)
76
+ return true
77
+ end
78
+
79
+ # If we ain't got no files, the glob failed
80
+ raise LoadError, "no such file to load -- #{arg}" if files.empty?
81
+ end
82
+ end
83
+
84
+ # If there's nothing to load, you're doing it wrong!
85
+ raise LoadError, "no files to load" if files.empty?
86
+
87
+ if options[:method] == :autoload
88
+ files.map! { |file| [file, File.expand_path(file)] }
89
+ files.each do |file, full_path|
90
+ __autoload(file, full_path, options)
91
+ end
92
+
93
+ return true
94
+ end
95
+
96
+ files.map! { |file| File.expand_path file }
97
+ files.sort!
98
+
99
+ begin
100
+ failed = []
101
+ first_name_error = nil
102
+
103
+ # Attempt to load each file, rescuing which ones raise NameError for
104
+ # undefined constants. Keep trying to successively reload files that
105
+ # previously caused NameErrors until they've all been loaded or no new
106
+ # files can be loaded, indicating unresolvable dependencies.
107
+ files.each do |file|
108
+ begin
109
+ Kernel.send(options[:method], file)
110
+ rescue NameError => ex
111
+ failed << file
112
+ first_name_error ||= ex
113
+ rescue ArgumentError => ex
114
+ # Work around ActiveSuport freaking out... *sigh*
115
+ #
116
+ # ActiveSupport sometimes throws these exceptions and I really
117
+ # have no idea why. Code loading will work successfully if these
118
+ # exceptions are swallowed, although I've run into strange
119
+ # nondeterministic behaviors with constants mysteriously vanishing.
120
+ # I've gone spelunking through dependencies.rb looking for what
121
+ # exactly is going on, but all I ended up doing was making my eyes
122
+ # bleed.
123
+ #
124
+ # FIXME: If you can understand ActiveSupport's dependencies.rb
125
+ # better than I do I would *love* to find a better solution
126
+ raise unless ex.message["is not missing constant"]
127
+
128
+ STDERR.puts "Warning: require_all swallowed ActiveSupport 'is not missing constant' error"
129
+ STDERR.puts ex.backtrace[0..9]
130
+ end
131
+ end
132
+
133
+ # If this pass didn't resolve any NameErrors, we've hit an unresolvable
134
+ # dependency, so raise one of the exceptions we encountered.
135
+ if failed.size == files.size
136
+ raise first_name_error
137
+ else
138
+ files = failed
139
+ end
140
+ end until failed.empty?
141
+
142
+ true
143
+ end
144
+
145
+ # Works like require_all, but paths are relative to the caller rather than
146
+ # the current working directory
147
+ def require_rel(*paths)
148
+ # Handle passing an array as an argument
149
+ paths.flatten!
150
+ return false if paths.empty?
151
+
152
+ source_directory = File.dirname caller.first.sub(/:\d+$/, '')
153
+ paths.each do |path|
154
+ require_all File.join(source_directory, path)
155
+ end
156
+ end
157
+
158
+ # Loads all files like require_all instead of requiring
159
+ def load_all(*paths)
160
+ require_all paths, :method => :load
161
+ end
162
+
163
+ # Loads all files by using relative paths of the caller rather than
164
+ # the current working directory
165
+ def load_rel(*paths)
166
+ paths.flatten!
167
+ return false if paths.empty?
168
+
169
+ source_directory = File.dirname caller.first.sub(/:\d+$/, '')
170
+ paths.each do |path|
171
+ require_all File.join(source_directory, path), :method => :load
172
+ end
173
+ end
174
+
175
+ # Performs Kernel#autoload on all of the files rather than requiring immediately.
176
+ #
177
+ # Note that all Ruby files inside of the specified directories should have same module name as
178
+ # the directory itself and file names should reflect the class/module names.
179
+ # For example if there is a my_file.rb in directories dir1/dir2/ then
180
+ # there should be a declaration like this in my_file.rb:
181
+ # module Dir1
182
+ # module Dir2
183
+ # class MyFile
184
+ # ...
185
+ # end
186
+ # end
187
+ # end
188
+ #
189
+ # If the filename and namespaces won't match then my_file.rb will be loaded into wrong module!
190
+ # Better to fix these files.
191
+ #
192
+ # Set $DEBUG=true to see how files will be autoloaded if experiencing any problems.
193
+ #
194
+ # If trying to perform autoload on some individual file or some inner module, then you'd have
195
+ # to always specify *:base_dir* option to specify where top-level namespace resides.
196
+ # Otherwise it's impossible to know the namespace of the loaded files.
197
+ #
198
+ # For example loading only my_file.rb from dir1/dir2 with autoload_all:
199
+ #
200
+ # autoload_all File.dirname(__FILE__) + '/dir1/dir2/my_file',
201
+ # :base_dir => File.dirname(__FILE__) + '/dir1'
202
+ #
203
+ # WARNING: All modules will be created even if files themselves aren't loaded yet, meaning
204
+ # that all the code which depends of the modules being loaded or not will not work, like usages
205
+ # of define? and it's friends.
206
+ #
207
+ # Also, normal caveats of using Kernel#autoload apply - you have to remember that before
208
+ # applying any monkey-patches to code using autoload, you'll have to reference the full constant
209
+ # to load the code before applying your patch!
210
+
211
+ def autoload_all(*paths)
212
+ paths.flatten!
213
+ return false if paths.empty?
214
+ require "pathname"
215
+
216
+ options = {:method => :autoload}
217
+ options.merge!(paths.pop) if paths.last.is_a?(Hash)
218
+
219
+ paths.each do |path|
220
+ require_all path, {:base_dir => path}.merge(options)
221
+ end
222
+ end
223
+
224
+ # Performs autoloading relatively from the caller instead of using current working directory
225
+ def autoload_rel(*paths)
226
+ paths.flatten!
227
+ return false if paths.empty?
228
+ require "pathname"
229
+
230
+ options = {:method => :autoload}
231
+ options.merge!(paths.pop) if paths.last.is_a?(Hash)
232
+
233
+ source_directory = File.dirname caller.first.sub(/:\d+$/, '')
234
+ paths.each do |path|
235
+ file_path = Pathname.new(source_directory).join(path).to_s
236
+ require_all file_path, {:method => :autoload,
237
+ :base_dir => source_directory}.merge(options)
238
+ end
239
+ end
240
+
241
+ private
242
+
243
+ def __autoload(file, full_path, options)
244
+ last_module = "Object" # default constant where namespaces are created into
245
+ begin
246
+ base_dir = Pathname.new(options[:base_dir]).realpath
247
+ rescue Errno::ENOENT
248
+ raise LoadError, ":base_dir doesn't exist at #{options[:base_dir]}"
249
+ end
250
+ Pathname.new(file).realpath.descend do |entry|
251
+ # skip until *entry* is same as desired directory
252
+ # or anything inside of it avoiding to create modules
253
+ # from the top-level directories
254
+ next if (entry <=> base_dir) < 0
255
+
256
+ # get the module into which a new module is created or
257
+ # autoload performed
258
+ mod = Object.class_eval(last_module)
259
+
260
+ without_ext = entry.basename(entry.extname).to_s
261
+ const = without_ext.split("_").map {|word| word.capitalize}.join
262
+
263
+ if entry.directory?
264
+ mod.class_eval "module #{const} end"
265
+ last_module += "::#{const}"
266
+ else
267
+ mod.class_eval do
268
+ puts "autoloading #{mod}::#{const} from #{full_path}" if $DEBUG
269
+ autoload const, full_path
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ end
276
+
277
+ include RequireAll