From: Rodrigo Rosenfeld Rosas Date: 2013-08-16T09:35:04-03:00 Subject: [ruby-core:56647] Re: [ruby-trunk - Feature #8781] Use require_relative() instead of require() if possible Em 16-08-2013 03:24, Aaron Patterson escreveu: > 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. :-) > Since we were discussing the design perspective, you just demonstrated how the design of using require can become much worse than using require_relative. When you're reading code you can be sure where to look for the files being loaded as expected while when using require you will always have to check $LOAD_PATH to be sure. I don't really think using require to allow such hacks is a good enough reason to favor require instead of require_relative... After all, Ruby already allows you to override code by monkey patching. Why would you need to override a full file?