Hey you! Stop using relative requires!

I recently came across two different programs that had this line in a
bin/ executable:

  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../
lib"))

This stuff makes me sad. The use of RubyGems is masking some bad
practices here. The above code would not work with a traditional site
installation.

I imagine this sort of thing has probably trickled down form Rails,
where programmers are accustom to deploying apps rather than releasing
them.

So here are the general rules (that I can think of off the top of my
head):

* Don't mess with the $LOAD_PATH. PERIOD.
* Use relative lookup only when you must, eg. using bundled HTML
templates.
* Any relative paths you do use must remain within the confines of
their main directory (eg. lib/)
* Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.
* Oh, and it should never need to necessary to require 'rubygems'.

These rules do not apply to building, eg. your Rakefile, running tests
and such. But try to follow them as much as possible anyway.

~Trans

Intransition wrote:

* Don't mess with the $LOAD_PATH. PERIOD.
* Use relative lookup only when you must, eg. using bundled HTML
templates.
* Any relative paths you do use must remain within the confines of
their main directory (eg. lib/)
* Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.
* Oh, and it should never need to necessary to require 'rubygems'.

Ok, I just finished "packaging"[1] my first app, and the only way I
could find that described how to do it, including the pickaxe book (for
ruby 1.9), breaks all but the last of those rules.

Care to enlighten me?

I have a structure of:

App
>----> bin -> app.rb
>----> initdb.rb
>----> lib
           >----> models -> *.rb
           >----> views -> *.rb
           >----> controllers -> *.rb
>----> config -> database.yaml
>----> db -> *.sqlite

I'm using wxRuby for the gui, ActiveRecord for the DB access, and
obviously, sqlite for the db.

How do I :

1) Make it so that I can call ruby <path to bin>/app.rb from anywhere in
the filesystem and have my app work?
2) Make 1) true for Linux, Windows and MacOSX?

Regards

Anthony

[1] because it isn't actually packaged yet, just internally consistent....

Why? require_relative has just been added to Ruby 1.9 and I wish it
had been there from the start. How else can you bundle some
application specific library code with an app?

If I don't require rubygems, none of my programs work.

I don't understand any of your points, so can you give some reasons?

···

On Wed, Oct 14, 2009 at 2:01 PM, Intransition <transfire@gmail.com> wrote:

I recently came across two different programs that had this line in a
bin/ executable:

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../
lib"))

This stuff makes me sad. The use of RubyGems is masking some bad
practices here. The above code would not work with a traditional site
installation.

I recently came across two different programs that had this line in a
bin/ executable:

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../
lib"))

This stuff makes me sad. The use of RubyGems is masking some bad
practices here. The above code would not work with a traditional site
installation.

I am not sure I understand why this is an issue. If it is in an
executable I write locally then I know where libraries reside (of
course, I would set RUBYLIB appropriately but for special tests or so
this might be necessary nevertheless).

If it is an executable which is part of a distribution, paths might be
as well known.

The only situation which could be problematic is an executable which
is deployed on arbitrary systems without modification. Hm...

I imagine this sort of thing has probably trickled down form Rails,
where programmers are accustom to deploying apps rather than releasing
them.

So here are the general rules (that I can think of off the top of my
head):

* Don't mess with the $LOAD_PATH. PERIOD.
* Use relative lookup only when you must, eg. using bundled HTML
templates.
* Any relative paths you do use must remain within the confines of
their main directory (eg. lib/)
* Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.
* Oh, and it should never need to necessary to require 'rubygems'.

These rules do not apply to building, eg. your Rakefile, running tests
and such. But try to follow them as much as possible anyway.

As far as I can see we would need at least two different sets of rules

1. requiring in library files
2. requiring in "main" files (executables)

Maybe more.

Kind regards

robert

PS: Why the changed name? Are you moving?

···

2009/10/14 Intransition <transfire@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

As someone who wrote a dependency-resolving code loading gem, I am extremely
dubious that one can always avoid code loading using relative paths.

How would you ordinarily go about loading some .rb files in a subdirectory
beneath the directory in which the current file is located?

···

On Wed, Oct 14, 2009 at 6:01 AM, Intransition <transfire@gmail.com> wrote:

Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.

--
Tony Arcieri
Medioh/Nagravision

It's not for site installation.

It's for packaged applications.

I wrote a pure ruby application that you can just unpack and run, no
need to "install" it on your system, and it uses the exact code you
show except it does not use the "/../".

This is ideal for situations when you do not want to require the users
to have a development environment ready to "install" the application.
Just having a ruby interpreter preinstalled from a binary package
suffices.

Thanks

Michal

···

2009/10/14 Intransition <transfire@gmail.com>:

I recently came across two different programs that had this line in a
bin/ executable:

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../
lib"))

This stuff makes me sad. The use of RubyGems is masking some bad
practices here. The above code would not work with a traditional site
installation.

for further clarification read:

<http://gist.github.com/54177&gt;and

http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise

<http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise&gt;

···

2009/10/14 Anthony Metcalf <anthony.metcalf@anferny.me.uk>

Intransition wrote:
> * Don't mess with the $LOAD_PATH. PERIOD.
> * Use relative lookup only when you must, eg. using bundled HTML
> templates.
> * Any relative paths you do use must remain within the confines of
> their main directory (eg. lib/)
> * Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.
> * Oh, and it should never need to necessary to require 'rubygems'.
>
>
Ok, I just finished "packaging"[1] my first app, and the only way I
could find that described how to do it, including the pickaxe book (for
ruby 1.9), breaks all but the last of those rules.

Care to enlighten me?

I have a structure of:

App
>----> bin -> app.rb
>----> initdb.rb
>----> lib
          >----> models -> *.rb
          >----> views -> *.rb
          >----> controllers -> *.rb
>----> config -> database.yaml
>----> db -> *.sqlite

I'm using wxRuby for the gui, ActiveRecord for the DB access, and
obviously, sqlite for the db.

How do I :

1) Make it so that I can call ruby <path to bin>/app.rb from anywhere in
the filesystem and have my app work?
2) Make 1) true for Linux, Windows and MacOSX?

Regards

Anthony

[1] because it isn't actually packaged yet, just internally consistent....

After reading your and previous comments and a brief bit of
unsuccessful googling, I decided it best if I wrote a blog entry on
the matter:

  http://proutils.github.com/2009/10/proper-require.html

Hope it helps.

Note the blog itself isn't quite "fully operational" -- no rss feed,
comments, and so forth yet, sorry. So please comment here.

···

On Oct 14, 1:03 pm, Tony Arcieri <t...@medioh.com> wrote:

On Wed, Oct 14, 2009 at 6:01 AM, Intransition <transf...@gmail.com> wrote:
> Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.

As someone who wrote a dependency-resolving code loading gem, I am extremely
dubious that one can always avoid code loading using relative paths.

How would you ordinarily go about loading some .rb files in a subdirectory
beneath the directory in which the current file is located?

Hi Michal

I've seen equivalent code in quite a few projects. Maybe they all have
the same reasoning, though I suspect they are just copying form one
another. Which is really why I wrote that blog post --so people at
least are aware.

I've thought about it further and I think maybe something "larger
picture" is actually taking place. I wrote a follow up post:

  http://proutils.github.com/2009/10/fhs-revolt.html

Thanks.

···

On Oct 26, 12:15 pm, Michal Suchanek <hramr...@centrum.cz> wrote:

2009/10/14 Intransition <transf...@gmail.com>:

> I recently came across two different programs that had this line in a
> bin/ executable:

> $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../
> lib"))

> This stuff makes me sad. The use of RubyGems is masking some bad
> practices here. The above code would not work with a traditional site
> installation.

It's not for site installation.

It's for packaged applications.

I wrote a pure ruby application that you can just unpack and run, no
need to "install" it on your system, and it uses the exact code you
show except it does not use the "/../".

This is ideal for situations when you do not want to require the users
to have a development environment ready to "install" the application.
Just having a ruby interpreter preinstalled from a binary package
suffices.

Thanks

Ah, this helps a little - I will stop requiring rubygems.

Of course, the correct thing:
require File.join( File.dirname( File.expand_path(__FILE__)), 'lib',
'helpers', 'precious')
..is also a relative require!

And I don't understand:
* Don't use a relative lookup for any ,rb or .so/.dll loading. PERIOD.

···

On Wed, Oct 14, 2009 at 3:57 PM, Louis-Philippe <default@spiralix.org> wrote:

for further clarification read:
54177’s gists · GitHub

<http://gist.github.com/54177&gt;and

http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise

<http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise&gt;

2009/10/14 Anthony Metcalf <anthony.metcalf@anferny.me.uk>

Louis-Philippe wrote:

for further clarification read:
54177’s gists · GitHub

<http://gist.github.com/54177&gt;and

http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise

<http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise&gt;

Thanks for the links. They are interesting.

Does make the require statements a wee bit wacky though, do people
really use

require File.join( File.dirname( File.expand_path(__FILE__)), 'lib',
'helpers', 'precious')

rather than

require 'lib/helpers/precious'

??

···

2009/10/14 Anthony Metcalf <anthony.metcalf@anferny.me.uk>

Quoting from that page:

   • Don't mess with the $LOAD_PATH. PERIOD.

My rule for rules:

   * Don't make rules that can never be broken. Period.

There are totally viable reasons to use $LOAD_PATH. For example, a Rails project is a self contained chunk of code that works together and it makes total sense to add certain portions of that project to the $LOAD_PATH, just as Rails does.

James Edward Gray II

···

On Oct 18, 2009, at 4:36 PM, Intransition wrote:

I decided it best if I wrote a blog entry on the matter:

http://proutils.github.com/2009/10/proper-require.html

Hope it helps.

Note the blog itself isn't quite "fully operational" -- no rss feed,
comments, and so forth yet, sorry. So please comment here.

Thomas Sawyer wrote:

I've thought about it further and I think maybe something "larger
picture" is actually taking place. I wrote a follow up post:

  http://proutils.github.com/2009/10/fhs-revolt.html

Thanks.

So... Anything to say about this? :slight_smile:

···

--
Posted via http://www.ruby-forum.com/\.

I believe there is a mistake: the second require should read

    # file /mygem/lib/helpers.rb
    require File.join( File.dirname( File.expand_path(__FILE__)),
'helpers', 'precious')

i.e. the "lib" is superfluous since helpers.rb does reside in lib already.

Whether people use that much I can't say. I believe usually require
'helpers/precious' is safe because if the load path is such that the
initial helpers.rb is found then it will also find the correct
precious.rb with the relative path. I do believe though that the
absolute path is more robust especially when using an explicit path to
require the library root file.

Kind regards

robert

···

2009/10/14 Anthony Metcalf <anthony.metcalf@anferny.me.uk>:

Louis-Philippe wrote:

for further clarification read:
54177’s gists · GitHub

<http://gist.github.com/54177&gt;and

http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise

<http://www.untilnil.com/2009/02/25/require-principle_of_least_surprise&gt;

2009/10/14 Anthony Metcalf <anthony.metcalf@anferny.me.uk>

Thanks for the links. They are interesting.

Does make the require statements a wee bit wacky though, do people
really use

require File.join( File.dirname( File.expand_path(__FILE__)), 'lib',
'helpers', 'precious')

rather than

require 'lib/helpers/precious'

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Don't make rules without proof reading them. :slight_smile:

SCNR

I think I agree to what you intended (if that is what you intended): rules should be checked against reality - if you cannot adhere to them under all conditions rather make them guidelines than rules - if at all.

Cheers

  robert

···

On 10/18/2009 11:54 PM, James Edward Gray II wrote:

On Oct 18, 2009, at 4:36 PM, Intransition wrote:

I decided it best if I wrote a blog entry on the matter:

http://proutils.github.com/2009/10/proper-require.html

Hope it helps.

Note the blog itself isn't quite "fully operational" -- no rss feed,
comments, and so forth yet, sorry. So please comment here.

Quoting from that page:

   • Don't mess with the $LOAD_PATH. PERIOD.

My rule for rules:

   * Don't make rules that can never be broken. Period.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

James Edward Gray II wrote:

Quoting from that page:

   � Don't mess with the $LOAD_PATH. PERIOD.

My rule for rules:

   * Don't make rules that can never be broken. Period.

There are totally viable reasons to use $LOAD_PATH. For example, a
Rails project is a self contained chunk of code that works together
and it makes total sense to add certain portions of that project to
the $LOAD_PATH, just as Rails does.

Tried to respond a few times, Google Groups is acting up it seems, so if
I ultimately triple post, my apologies.

To be brief, you are correct in that these rules do not apply to Rails
apps. I'm talking about Ruby projects. I made a note of it in the post
to clarify that fact.

Thanks.

···

--
Posted via http://www.ruby-forum.com/\.

I'm pretty sure we can come up with non-Rails applications scenarios where they don't apply. I vote we just reject the dogma and focus on the problems it can cause.

I'm not saying you're wrong about the issue. I'm just saying that telling us to never do something, is just a turn off.

James Edward Gray II

···

On Oct 19, 2009, at 4:30 PM, Thomas Sawyer wrote:

James Edward Gray II wrote:

Quoting from that page:

  � Don't mess with the $LOAD_PATH. PERIOD.

My rule for rules:

  * Don't make rules that can never be broken. Period.

There are totally viable reasons to use $LOAD_PATH. For example, a
Rails project is a self contained chunk of code that works together
and it makes total sense to add certain portions of that project to
the $LOAD_PATH, just as Rails does.

Tried to respond a few times, Google Groups is acting up it seems, so if
I ultimately triple post, my apologies.

To be brief, you are correct in that these rules do not apply to Rails
apps. I'm talking about Ruby projects. I made a note of it in the post
to clarify that fact.

James Edward Gray II wrote:

I'm pretty sure we can come up with non-Rails applications scenarios
where they don't apply. I vote we just reject the dogma and focus on
the problems it can cause.

I'm not saying you're wrong about the issue. I'm just saying that
telling us to never do something, is just a turn off.

Ok. But I think maybe you are missing my point. I'm not pushing a dogma.
I am making an emphasis: There is no reason to use relative loading at
all in those cases. To re-phase... I'm not telling you not to do it. I
am telling you there is absolutely no need for you to do it.

I'm very much doubt there are any outlay cases. But if there are, I'd be
more than ready to amend these "rules".

Also, let me just note that I actually like relative loading, b/c I like
folder based packaging (I'm a fan of GoboLinux for instance). But
without the major distro's embrace it's not something that can be
completely relied upon (hence the bin/ example). If it were, I think
Ruby would have better support for it too. I mean really, doesn't

  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) +
"/../lib"))

give off just a little code smell? :wink:

···

--
Posted via http://www.ruby-forum.com/\.

Thomas Sawyer wrote:

James Edward Gray II wrote:

I'm pretty sure we can come up with non-Rails applications scenarios
where they don't apply. I vote we just reject the dogma and focus on
the problems it can cause.

I'm not saying you're wrong about the issue. I'm just saying that
telling us to never do something, is just a turn off.

Ok. But I think maybe you are missing my point. I'm not pushing a dogma. I am making an emphasis: There is no reason to use relative loading at all in those cases. To re-phase... I'm not telling you not to do it. I am telling you there is absolutely no need for you to do it.

I'm very much doubt there are any outlay cases. But if there are, I'd be more than ready to amend these "rules".

Also, let me just note that I actually like relative loading, b/c I like folder based packaging (I'm a fan of GoboLinux for instance). But without the major distro's embrace it's not something that can be completely relied upon (hence the bin/ example). If it were, I think Ruby would have better support for it too. I mean really, doesn't

What would you suggest in the case of multiple versions of a module for testing purposes? If everything is "hard coded" to go to a specific directory than all versions would use the same code and defeat the purpose of having the different versions.

···

  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))

give off just a little code smell? :wink:

Just a general description of how you handle code loading within a gem
that's "under development" (i.e. all code lives in a directory somewhere,
not in a gem) while requiring minimal/no changes to a "released" gem (one
which loads through a RubyGems-defined LOAD_PATH) would be helpful.

Or for that matter, how about selectively pulling in files which require the
toplevel gem but exist under subdirectories within the gem, and need to load
the gem in order to function? How would you handle that?

If there's some magic tricks I'm missing to solving these sorts of
conundrums, I'm certainly interested in hearing them. I think for the most
part something like require_all/require_rel takes care of a lot of the
problems of code loading, and certainly isn't my own solution, just my
implementation, but I'm curious how people solve these sorts of problems
without it.

···

On Mon, Oct 19, 2009 at 9:50 PM, Thomas Sawyer <transfire@gmail.com> wrote:

Ok. But I think maybe you are missing my point. I'm not pushing a dogma.
I am making an emphasis: There is no reason to use relative loading at
all in those cases. To re-phase... I'm not telling you not to do it. I
am telling you there is absolutely no need for you to do it.

I'm very much doubt there are any outlay cases. But if there are, I'd be
more than ready to amend these "rules".

--
Tony Arcieri
Medioh/Nagravision