Require_relative? why didn't we "relative do"

I wonder if it would been better if we had gone another route with the
whole #require_relative thing. Instead of a special require method, we
could have a method that adds the current file’s directory to the top of
the $LOAD_PATH temporarily while a block executes.

For example, lets say we have a library `fruit_basket’ with:

lib/
  fruit_basket.rb
  fruit_basket/
    grape.rb
    orange.rb

Then in fruit_basket.rb:

relative do
  require 'grape'
  require 'orange'
end

Assuming #relative to be the name of such a method.

This is actually quite easy to implement in pure Ruby and would not have
required a C-based patch to Ruby core.

On Jun 12, 2012, at 9:34 PM 6/12/12, Intransition wrote:

Then in fruit_basket.rb:

Hey Intransition.

you might have better luck emailing ruby-core if you’re interested in
this an can’t work it out.

Have you looked through the ruby-lang archives? The first hit I found
for require_relative was this: http://www.ruby-forum.com/topic/148978
which seems to indicate there wasn’t much discussion about the
functionality. What’s cool is that it also shows that require_relative
was originally ruby code, not C.

Assuming that it was rewritten in C (I haven’t checked), I imagine it
was to ensure performance. 1.9 had a lot of performance improvements
over 1.8.

Jams

What for? This is needlessly munging a global variable. Also, if one
of the required scripts also happen to require something, it will
become a relative require, too. (Unless you add some magical guard
code for this, and then we’re on a slippery slope.)

– Matma R.

On Wednesday, June 13, 2012 10:40:08 AM UTC-4, Bartosz Dziewoński wrote:

What for? This is needlessly munging a global variable. Also, if one
of the required scripts also happen to require something, it will
become a relative require, too. (Unless you add some magical guard
code for this, and then we’re on a slippery slope.)

Ah good point. It wouldn’t become relative exactly, but it could
(however
unlikely) conflict name wise. However, since one is requiring relative
to a
current file it is more likely that one would be aware of any such
issue.
Say a local ostruct.rb file when one actuall wants the ruby one.

To clarify my implementation concept was something along the lines of:

def relative(&block)
  dir = File.dirname(eval('__FILE__', block.binding))
  $LOAD_PATH.unshift(dir)
  block.call
  $LOAD_PATH.delete(dir)
end

Obviously that would need to be improved upon, but that conveys the idea
of
it.

Anyway, you are probably correct. It just struck me b/c a pure Ruby
implementation of #require_relative is not very robust as it has to use
caller, so I think its interesting that this block form never cropped
up
before. If it had, I wonder if #require_relative ever would have come
about
–there was such resistance to it by matz for so long.

try this

def require(path)
@rel ? require_relative(path) : Kernel.require(path)
end

def relative
@rel = true
yield
@rel = false
end

or something similar

On Jun 12, 2012, at 20:34, Intransition wrote:

Then in fruit_basket.rb:

relative do
  require 'grape'
  require 'orange'
end

Say we also have the library “color”:

lib/
orange.rb

And “flavor”:

lib/
grape.rb
banana.rb

Which files are loaded with:

gem ‘color’
gem ‘flavor’
require ‘fruit_basket’

Say we have grafted fruits in fruit_basket such as
lib/fruit_basket/lemon-orange.rb:

lemon seedling with orange grafted on

require ‘lemon’
require ‘orange’

Note that this file depends on being loaded from inside
fruit_basket.rb’s relative block, but that is not explicitly stated:

lib/fruit_basket.rb:
relative do
require ‘lemon-orange’
# …
end

gem ‘color’
gem ‘flavor’
require ‘fruit_basket’

Which files were loaded?

require_relative doesn’t have the problem of the reader of the source
needing external information to determine “which directory does this
require operate in?” since it is explicit. I don’t see how you make it
explicit for require inside a relative block.

Say you have two threads:

gem ‘color’
gem ‘flavor’

Thread.start do
require ‘orange’
end

Thread.start do
require ‘fruit_basket’
end

Are one or two “orange.rb” files loaded? Which ones?

On Wednesday, June 13, 2012 9:20:34 AM UTC-4, Jams wrote:

Assuming that it was rewritten in C (I haven’t checked), I imagine it was
to ensure performance. 1.9 had a lot of performance improvements over 1.8.

Unfortunately I learned a few months ago that #require_relative has not
been optimized, so it is hardly any better for being written in C.
However,
I am hopeful that one day someone will take the time to optimize it as
it
is ripe for such treatment and then it could readily help boost load
speeds.