RFC - One word alias for require_relative

This is a simple Request for Comments.

Scenario:

require_relative ‘lib/alter’
require ‘alibrary’

Some project manager complains about “require_relative”, and asks you
to find a one-word alias.

Which name would you select and for what reasons?

Requirements
must:

  • one word

optional:

  • ideally a 7 letter word

.

On Jun 11, 2011, at 1:35 PM, Ilias L. wrote:

Which name would you select and for what reasons?

Requirements
must:

  • one word

optional:

  • ideally a 7 letter word

require ‘alibrary’
locally ‘lib/alter’

.


http://lazaridis.com

(Uh oh. I replied to Ilias! :wink:

-Rob

Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/

On Jun 11, 1:35pm, Ilias L. [email protected] wrote:

Which name would you select and for what reasons?

Requirements
must:

  • one word

optional:

  • ideally a 7 letter word

Okay, I’m willing to respond to this b/c I think there’s an
interesting alternative here that would be an improvement over the
current system.[1]

Instead of having two different methods, have the one #require that
does both. How would it work? Kind of like constant lookup. First the
require method would look locally, if it failed to find it there it
could look relative to the current loading project, and then from
there globally. Of course the problem is name conflict, but that can
easily be solved. Let’s say I have lib file called ‘ostruct.rb’, say
it has an extension to ruby’s OpenStruct class. Because of the
relative loading we wouldn’t be able to just require ‘ostruct’ b/c it
would try to load itself. So instead we have to tell it to look
globally. We just need a way to denote it, e.g.

require '::ostruct'

We could also be more specific and actually specify the library it is
in, which could be used to speed up load times and prevent name
clashes altogether, with:

require 'ruby:ostruct'.

This idea of course presents backward compatibility issues, but it is
a way to do it that actually improves the robustness and efficiency of
the load system.

[1] Hey, get what you can out of him.

On Sat, Jun 11, 2011 at 9:12 PM, Intransition [email protected]
wrote:

This idea of course presents backward compatibility issues, but it is
a way to do it that actually improves the robustness and efficiency of
the load system.

If it breaks backwards compatibility, it’s neither effective nor
robust, I’d say.

Especially since your idea introduces a lot of mental overhead on my
part:

Do I want a local or a global file? What’s the syntax for a global
require, again? And it’s almost, but not entirely, completely unlike
accessing nested constants (Module::Class vs ::file).

And running non “::require”-aware code leads to fun bugs and security
issues (imagine a “ostruct” file in the load path that wipes your
filesystem. The joys…).

On the flip side, require and require_relative make it completely
clear that I load either globally or in relation to my source files
without having to remember what a particular bit of line noise
means.

If the issue is that you have to type so much more, set up a macro in
your favourite editor. Or if you happen to use AutoHotKey:
::r#::require
::rr#::require_relative

(using the # to avoid situations where you want to type literal “r” and
"rr"s)

You can then tell your project manager to do some actual work, instead
of worrying about 8 bytes worth of storage.


Phillip G.

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibnitz

On Sat, Jun 11, 2011 at 11:08 PM, Intransition [email protected]
wrote:

If it breaks backwards compatibility, it’s neither effective nor
robust, I’d say.

They are different. Of course it’s not robust if you are mixing two
incompatible systems. Obviously we wouldn’t do that.

Mu. Address the point I made.

Especially since your idea introduces a lot of mental overhead on my part:

Not really, it similar enough to overhead that we use for Ruby already
in referencing constants. I mean really, it’s :: and package- name:file-path that’s all there is to know.

require # works globally
require_relative # works relative to current working directory

What these methods do is encoded in the method name. I don’t have to
remember a thing, since the method tells me what it does, and it
even works when require[_relative] loads from a variable.

And running non “::require”-aware code leads to fun bugs and security
issues (imagine a “ostruct” file in the load path that wipes your
filesystem. The joys…).

That can already happen, btw. Very easily in fact. But again you are
suggesting mixing two incompatible systems.

Not without “.” in the loadpath it can’t:
PS C:\temp> irb

require “ostruct”
=> true
require “./ostruct”
This is not Ruby’s OpenStruct library.
=> true
exit
PS C:\temp> cat .\ostruct.rb
puts “This is not Ruby’s OpenStruct library.”
PS C:\temp> ruby -v
ruby 1.9.2p180 (2011-02-18) [i386-mingw32]

No, that’s not it. You missed the big benefit here. By specifying the
package-name in the require, we can guarantee the origin of the file.

No, we can’t. Look up is still along the path, and something that is
named identically within the loadpath that gets loaded first still
blows up in your face.

As things are today, a gem author could readily play havoc with the
load system --which is why isolation systems sprung up, like isolate
and (partially) Bundler.

Which your system doesn’t mitigate against at all. And it cannot, ever
(nor does Bundler: It is a poor man’s version and dependency control).
Once code is on a machine, it can do whatever it wants. Ruby just
makes it easier to modify its own classes, but the vector is still
there: external code executed locally.

Without making gem signing the default, and have Ruby / RubyGems load
only signed source files, you have no idea who created the code
you’ve downloaded. And even then you have to trust the certificate,
and that the private key with which the code was signed wasn’t
compromised somehow.

Without auditing code, you have no idea what the code does to your
machine, and who prevents anyone from claiming “I’m part of Ruby’s
namespace”?


Phillip G.

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibnitz

Afternoon,

On Sat, Jun 11, 2011 at 10:35 AM, Ilias L.
[email protected]wrote:

This is a simple Request for Comments.

Scenario:

require_relative ‘lib/alter’
require ‘alibrary’

Some project manager complains about “require_relative”, and asks you
to find a one-word alias.

Fire the project manager or get another job - any bozo that cares about
9
descriptive characters isn’t worth the time…

John

P.S. This now moves into the lead as to the stupidest of Ilias’
questions
thus far. I am surprised that this isn’t a barrier to something.

On Jun 11, 3:51pm, Phillip G. [email protected]
wrote:

On Sat, Jun 11, 2011 at 9:12 PM, Intransition [email protected] wrote:

This idea of course presents backward compatibility issues, but it is
a way to do it that actually improves the robustness and efficiency of
the load system.

If it breaks backwards compatibility, it’s neither effective nor
robust, I’d say.

They are different. Of course it’s not robust if you are mixing two
incompatible systems. Obviously we wouldn’t do that.

Especially since your idea introduces a lot of mental overhead on my part:

Not really, it similar enough to overhead that we use for Ruby already
in referencing constants. I mean really, it’s :: and package- name:file-path that’s all there is to know.

Do I want a local or a global file? What’s the syntax for a global
require, again? And it’s almost, but not entirely, completely unlike
accessing nested constants (Module::Class vs ::file).

And running non “::require”-aware code leads to fun bugs and security
issues (imagine a “ostruct” file in the load path that wipes your
filesystem. The joys…).

That can already happen, btw. Very easily in fact. But again you are
suggesting mixing two incompatible systems.

On the flip side, require and require_relative make it completely
clear that I load either globally or in relation to my source files
without having to remember what a particular bit of line noise
means.

If the issue is that you have to type so much more, set up a macro in
your favourite editor. Or if you happen to use AutoHotKey:
::r#::require
::rr#::require_relative

No, that’s not it. You missed the big benefit here. By specifying the
package-name in the require, we can guarantee the origin of the file.
As things are today, a gem author could readily play havoc with the
load system --which is why isolation systems sprung up, like isolate
and (partially) Bundler.

On Jun 11, 6:24pm, Phillip G. [email protected]
wrote:

On Sat, Jun 11, 2011 at 11:08 PM, Intransition [email protected] wrote:

If it breaks backwards compatibility, it’s neither effective nor
robust, I’d say.

They are different. Of course it’s not robust if you are mixing two
incompatible systems. Obviously we wouldn’t do that.

Mu. Address the point I made.

Then call it #another_way_to_load_a_ruby_file or #awtlarf to meet
IIias’ 7-letter requirement;. Whatever. It’s beside the point.

remember a thing, since the method tells me what it does, and it
even works when require[_relative] loads from a variable.

You still have to remember the name of the method. Moreover my system
does things yours does not. So to be fair you would need another
method or two, and a hash option too, e.g.

require ‘ostruct’, :library=>‘ruby’

require “./ostruct”

This is not Ruby’s OpenStruct library.
=> true>> exit

PS C:\temp> cat .\ostruct.rb
puts “This is not Ruby’s OpenStruct library.”
PS C:\temp> ruby -v
ruby 1.9.2p180 (2011-02-18) [i386-mingw32]

What’s your point? I don’t see how that has anything to do with what
you said.

No, that’s not it. You missed the big benefit here. By specifying the
package-name in the require, we can guarantee the origin of the file.

No, we can’t. Look up is still along the path, and something that is
named identically within the loadpath that gets loaded first still
blows up in your face.

That’s not it. The suggestion I am making moves beyond the simple path
system Ruby now uses. It would require that Ruby understand packages.
So it’s not “still along the path”.

As things are today, a gem author could readily play havoc with the
load system --which is why isolation systems sprung up, like isolate
and (partially) Bundler.

Which your system doesn’t mitigate against at all. And it cannot, ever
(nor does Bundler: It is a poor man’s version and dependency control).
Once code is on a machine, it can do whatever it wants. Ruby just
makes it easier to modify its own classes, but the vector is still
there: external code executed locally.

Yes it does. I use it all the time. I wrote such a system and use if
for development.

Without making gem signing the default, and have Ruby / RubyGems load
only signed source files, you have no idea who created the code
you’ve downloaded. And even then you have to trust the certificate,
and that the private key with which the code was signed wasn’t
compromised somehow.

You’re now talking about another subject.

Without auditing code, you have no idea what the code does to your
machine, and who prevents anyone from claiming “I’m part of Ruby’s
namespace”?

Ruby.

On Jun 11, 8:32pm, Phillip G. [email protected]
wrote:

On Sun, Jun 12, 2011 at 1:42 AM, Intransition [email protected] wrote:

You still have to remember the name of the method. Moreover my system
does things yours does not. So to be fair you would need another
method or two, and a hash option too, e.g.

require ‘ostruct’, :library=>‘ruby’

What for?

It restricts where the file ‘ostruct’ can be found. In this case to
ruby’s standard library.

And yes, I have to remember the method name. A method name that’s much
more mnemonic than ‘::whatever’.

Fair enough. The device isn’t as important as what it accomplishes. A
hash option can work too.

What’s your point? I don’t see how that has anything to do with what
you said.

You can’t accidentally pollute the namespace if the file doesn’t get
loaded by default. One of the reasons we have “require” and
“require_relative”.

Quite true. #require_relative is a great feature of 1.9. There’s still
requiring from other libraries though, and if some one follows bad
practices the wrong file can get loaded.

That’s not it. The suggestion I am making moves beyond the simple path
system Ruby now uses. It would require that Ruby understand packages.
So it’s not “still along the path”.

Please. Then I just define a package, put that someplace first in the
loadpath, and boom, your system blowing up in your face again.

That’s not how it works. You can’t put something first in the load
path. Rather than a simple list of paths, such a system uses a table
of { ‘packgname’ => ‘path/to/package’ }. Actually it’s a little more
complicated than that b/c of versions and internal require_paths
settings but that’s the basic idea.

Ruby.

How? Since Ruby can execute arbitrary OS-level commands with system()
or ``, how can Ruby prevent namespace pollution?

I think we are talking about two different things. I’m only talking
about preventing the wrong file from being loaded. Not anything to do
with what’s in a file.

On Sun, Jun 12, 2011 at 5:07 AM, Intransition [email protected]
wrote:

It restricts where the file ‘ostruct’ can be found. In this case to
ruby’s standard library.

See below.

Please. Then I just define a package, put that someplace first in the
loadpath, and boom, your system blowing up in your face again.

That’s not how it works. You can’t put something first in the load
path. Rather than a simple list of paths, such a system uses a table
of { ‘packgname’ => ‘path/to/package’ }. Actually it’s a little more
complicated than that b/c of versions and internal require_paths
settings but that’s the basic idea.

Since you need to check for a package in different places (user
specific and global at the very least), you have a load path of some
sort. As long as my package comes first, your system can be broken,
subverted, by my package.

I think we are talking about two different things. I’m only talking
about preventing the wrong file from being loaded. Not anything to do
with what’s in a file.

Of course it has to do with what is in the file. If you execute a
file that arbitrarily loads code (like a Ruby file, for example, since
the file’s contents get executed on load time already), your system
can be subverted. So, you do a lot of work to prevent something that
you cannot prevent to begin with. Not without changing how operating
systems work these days (i.e. instead of executing everything that’s
not blacklisted, only that which is whitelisted gets executed).


Phillip G.

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibnitz

On Sun, Jun 12, 2011 at 1:42 AM, Intransition [email protected]
wrote:

You still have to remember the name of the method. Moreover my system
does things yours does not. So to be fair you would need another
method or two, and a hash option too, e.g.

require ‘ostruct’, :library=>‘ruby’

What for?

And yes, I have to remember the method name. A method name that’s much
more mnemonic than ‘::whatever’.

What’s your point? I don’t see how that has anything to do with what
you said.

You can’t accidentally pollute the namespace if the file doesn’t get
loaded by default. One of the reasons we have “require” and
“require_relative”.

That’s not it. The suggestion I am making moves beyond the simple path
system Ruby now uses. It would require that Ruby understand packages.
So it’s not “still along the path”.

Please. Then I just define a package, put that someplace first in the
loadpath, and boom, your system blowing up in your face again.

Which your system doesn’t mitigate against at all. And it cannot, ever
(nor does Bundler: It is a poor man’s version and dependency control).
Once code is on a machine, it can do whatever it wants. Ruby just
makes it easier to modify its own classes, but the vector is still
there: external code executed locally.

Yes it does. I use it all the time. I wrote such a system and use if
for development.

Every programmer can invent a cypher he, himself, cannot break, as well.

Unless you wrote your own OS that allows only the execution of
specifically whitelisted binaries and script files (you have to
prevent arbitrary code execution within a Ruby interpreter, too, after
all, and just whitelisting the Ruby binary won;t work for that), code
that is running on your machine, can manipulate your machine.

Without auditing code, you have no idea what the code does to your
machine, and who prevents anyone from claiming “I’m part of Ruby’s
namespace”?

Ruby.

How? Since Ruby can execute arbitrary OS-level commands with system()
or ``, how can Ruby prevent namespace pollution?


Phillip G.

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibnitz

Phillip G. wrote in post #1004744:

You can then tell your project manager to do some actual work

I’m sure it was an innocent remark but as a project manager myself, I
would rather you didn’t go around spreading these sorts of ideas too
much.

Back in the blissful days before I understood the $LOAD_PATH or the
difference between Dir.pwd and File.dirname(__FILE__), I could
require "file" and it would work (unless I was in another dir).
require_relative
isn’t universally implemented, and doesn’t seem to play well with
others.
It’s just generally been unavailable / not worked right for me to the
point
that I prefer to use File.dirname(__FILE__) + "/file"

What if, instead of having CWD in the load path, we had
File.dirname(__FILE__)? Essentially, CWD of the file that the require
statement is originated through. In the same way that every file has its
own
__FILE__ variable, what if the $LOAD_PATH included the current
file’s
dir, for any given file? Then the old interface would work again, it
would
be simpler to think about, security risks of CWD in the load path would
be
addressed, and most importantly, I could write beautiful code again (I
die a
little bit inside each time I write FILE).

Of course, I have no idea if it’s even possible, and it’s not
immediately
clear to me how it would affect gems. Still, thought I’d put it out
there.

On 11 , 20:48, Rob B. [email protected] wrote:

to find a one-word alias.
require ‘alibrary’
locally ‘lib/alter’

“Locally”, because it’s an inclusion from the local directories, and
not from the global library directories.

Yes, this one sounds good.

http://lazaridis.com

(Uh oh. I replied to Ilias! :wink:

(You will be punished with 37 spam mails)

.

On Jun 12, 5:59am, Josh C. [email protected] wrote:

__FILE__ variable, what if the $LOAD_PATH included the current file’s
dir, for any given file? Then the old interface would work again, it would
be simpler to think about, security risks of CWD in the load path would be
addressed, and most importantly, I could write beautiful code again (I die a
little bit inside each time I write FILE).

Of course, I have no idea if it’s even possible, and it’s not immediately
clear to me how it would affect gems. Still, thought I’d put it out there.

Hi Josh, your idea is essentially the basis to what I was suggesting
in my earlier comments. By adding the current files path to $LOAD_PATH
you make #require and #relative_require one and the same. But that can
cause problems if you have name conflicts between a local file and a
file in another library. Consider the example I gave. If you wanted to
create an extension for OpenStruct, and created a file called
ostruct.rb in your project, how would you load Ruby’s ‘ostruct.rb’
file?

Yep, that just re-introduces the security issue that had us remove .
from $:
in the first place.

And I wrote a gem that backports require_relative to 1.8, so you can use
it
everywhere. :wink: http://rubygems.org/gems/require_relative

On 11 , 22:12, Intransition [email protected] wrote:

to find a one-word alias.
Okay, I’m willing to respond to this
[…] - (changing/extending context)

But you haven’t responded.

The response would be to suggest a word.

This idea of course presents backward compatibility issues, but it is
a way to do it that actually improves the robustness and efficiency of
the load system.

The process would be:

  • let “require” and “require_relative” work as usual (backwards
    compatibility)
  • define a new keyword for the new load system (e.g. “ensure”)
  • engineer this system from scratch
    • including a non-intrusive dynamic OO library-system which builds
      on the strengths of the language (dynamic, oo, etc.)

The term “engineer” refers to the process.

But this is really ways out of the current topic here.

As said, just looking for a word, ideally with 7 letters.

.

On Jun 12, 11:35am, Steve K. [email protected] wrote:

Yep, that just re-introduces the security issue that had us remove . from $:
in the first place.

And I wrote a gem that backports require_relative to 1.8, so you can use it
everywhere. :wink:http://rubygems.org/gems/require_relative

Hompage link seems to be broken

Is this in backports (GitHub - marcandre/backports: The latest features of Ruby backported to older versions.), btw?

I’m wondering if I can just start doing 1.9+ only from now on, and if
the end user wants to use my stuff with 1.8.x they can add RUBYOPT=“-
rbackports”, or something along those lines. Could something like that
do the job?

Hompage link seems to be broken

I’ll get that fixed, thanks. Till then,

Is this in backports (GitHub - marcandre/backports: The latest features of Ruby backported to older versions.), btw?

I believe that backports has it too, yes.

On 11 , 20:35, Ilias L. [email protected] wrote:

Which name would you select and for what reasons?

Requirements
must:

  • one word

optional:

  • ideally a 7 letter word

As there is just one suggestion till now, I’ll add two suggestions
myself, thus we have 3:

locally ‘lib/alter’ # locally located file
require ‘alibrary’

new suggestions:

include ‘lib/alter’ # the commonly known “include”
require ‘alibrary’

uniload ‘lib/alter’ # universal load
require ‘alibrary’

.