From: Aaron Patterson Date: 2013-08-16T15:24:43+09:00 Subject: [ruby-core:56643] Re: [ruby-trunk - Feature #8781] Use require_relative() instead of require() if possible On Fri, Aug 16, 2013 at 03:00:59PM +0900, SASADA Koichi wrote: > (2013/08/16 14:21), Aaron Patterson wrote: > > If you move the file, then all calls to `require_relative` in that file > > must be changed. If you had just used `require`, the file can be moved > > without changes. > > Which case? > > For example, there are files: > foo.rb > foo/bar/a.rb > > And foo.rb has "require 'foo/bar/a'". > > If you move foo/bar/a.rb to foo/bar/b.rb, then you need to rewrite to > "require 'foo/bar/b'". > > If you move foo/bar/a.rb to foo/baz/a.rb, then you need to rewrite to > "require 'foo/baz/a'". Yes, you changed the files that *depend on* the source for 'foo/bar/a', but 'foo/bar/a.rb' itself did not change. If something *you depend on* changes location, then yes, you should change your code. Here is an example with require_relative: $ mkdir -p lib/foo/bar $ touch lib/foo.rb $ echo "require_relative '../../foo'" > lib/foo/bar/baz.rb $ ruby -I lib -r'foo/bar/baz' -e 0 $ mv lib/foo/bar/baz.rb lib/foo/ $ ruby -I lib -r'foo/baz' -e 0 /Users/aaron/git/example/lib/foo/baz.rb:1:in `require_relative': cannot load such file -- /Users/aaron/git/example/foo (LoadError) from /Users/aaron/git/example/lib/foo/baz.rb:1:in `' from /Users/aaron/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require' from /Users/aaron/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require' $ In the above example, "foo.rb" did not change location, yet I have to change the call to `require_relative`. foo/bar/baz.rb depends on foo.rb. foo.rb did not change locations, so why do I have to change my code? Let's take the same example, "foo/bar/baz.rb" that depends on "foo.rb", but instead use `require`: $ mkdir -p lib/foo/bar $ echo "require 'foo'" > lib/foo/bar/baz.rb $ touch lib/foo.rb $ ruby -I lib -r'foo/bar/baz' -e 0 $ mv lib/foo/bar/baz.rb lib/foo/ $ ruby -I lib -r'foo/baz' -e 0 $ My dependency, "foo.rb", did not change locations, so I don't need to change my code. "foo/bar/baz.rb" works as-is, no matter where it is on the filesystem. :-) -- Aaron Patterson http://tenderlovemaking.com/