RFC - One word alias for require_relative

I

Ilias Lazaridis

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

..
 
R

Rob Biedenharn

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

require 'alibrary'
locally 'lib/alter'

(Uh oh. I replied to Ilias! ;-)

-Rob

Rob Biedenharn
(e-mail address removed) http://AgileConsultingLLC.com/
(e-mail address removed) http://GaslightSoftware.com/
 
I

Intransition

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

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 '::eek:struct'

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:eek:struct'.

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.
 
P

Phillip Gawlowski

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.

--=20
Phillip Gawlowski

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.
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- Leibnitz
 
I

Intransition

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 pa=
rt:

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.
 
P

Phillip Gawlowski

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.
art:

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.
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> irbThis is not Ruby's OpenStruct library.
=3D> truePS 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"?


--=20
Phillip Gawlowski

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.
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- Leibnitz
 
J

John W Higgins

[Note: parts of this message were removed to make it a legal post.]

Afternoon,

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.
 
I

Intransition

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.
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.

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=3D>'ruby'
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"
=3D> true
This is not Ruby's OpenStruct library.
=3D> 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, 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".
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.
 
P

Phillip Gawlowski

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.

=A0require 'ostruct', :library=3D>'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.
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.

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

--=20
Phillip Gawlowski

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.
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- Leibnitz
 
I

Intransition

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 =A0'::whatever'.

Fair enough. The device isn't as important as what it accomplishes. A
hash option can work too.
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.
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' =3D> '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.
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.



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.
 
P

Phillip Gawlowski

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

See below.
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 =A0{ 'packgname' =3D> '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).

--=20
Phillip Gawlowski

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.
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- Leibnitz
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

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.
 
I

Ilias Lazaridis

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.
(Uh oh. I replied to Ilias! ;-)

(You will be punished with 37 spam mails)

..
 
I

Ilias Lazaridis

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.

..
 
I

Intransition

Back in the blissful days before I understood the `$LOAD_PATH` or the
difference between `Dir.pwd` and `File.dirname(__FILE__)`, I could `requi= re
"file"` and it would work (unless I was in another dir). `require_relativ= e`
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 poi= nt
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 woul= d
be simpler to think about, security risks of CWD in the load path would b= e
addressed, and most importantly, I could write beautiful code again (I di= e 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=
 
S

Steve Klabnik

[Note: parts of this message were removed to make it a legal post.]

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. ;) http://rubygems.org/gems/require_relative
 
I

Intransition

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. ;)http://rubygems.org/gems/require_relative

Hompage link seems to be broken

Is this in backports (https://github.com/marcandre/backports), 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=3D"-
rbackports", or something along those lines. Could something like that
do the job?
 
I

Ilias Lazaridis

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

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'

..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top