Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Require when Executed file is required by another file.

Reply
Thread Tools

Require when Executed file is required by another file.

 
 
Zev Blut
Guest
Posts: n/a
 
      02-18-2005
Hello,

My colleagues and I just encountered an interesting gotcha with
"require".

Put the following in a file called "req1.rb"

-------------- [req1.rb]
#!/usr/local/bin/ruby1.8 -w

puts "$0 #{$0}"
base = $0.split("/")
PATH = base[0...(base.size - 1)].join("/")

def jump
require "req2"
end

puts "Fun"

if __FILE__ == $0
puts "Require 1"
jump
end
---------- [req1.rb]

And then put the following in another file called "req2.rb"

---------- [req2.rb]
require "#{PATH}/req1"

puts "Require 2"
---------- [req2.rb]

Now run req1.rb from the full path.

Here is an example of my output:
========
$ /home/zev/projects/rubyplay/recurse_require/req1.rb
$0 /home/zev/projects/rubyplay/recurse_require/req1.rb
Fun
Require 1
$0 /home/zev/projects/rubyplay/recurse_require/req1.rb
/home/zev/projects/rubyplay/recurse_require/req1.rb:5: warning:
already initialized constant PATH

/home/zev/projects/rubyplay/recurse_require/req1.rb:7: warning: method
redefined; discarding old jump

Fun
Require 1
Require 2
=========

Notice that the __FILE__ == $0 gets called twice!
Also the fact that PATH and jump get redefined too...

Is there a way to easily stop this?

Thanks,
Zev


 
Reply With Quote
 
 
 
 
Nospam
Guest
Posts: n/a
 
      02-18-2005
It seems that although require normally makes sure a certain files only
gets included once require somehow doesn't take into account the file
the interpreter first included.

Regards,

Peter
 
Reply With Quote
 
 
 
 
Zev Blut
Guest
Posts: n/a
 
      02-18-2005
On Fri, 18 Feb 2005 21:09:47 +0900, Nospam
<(E-Mail Removed)-nonsense.org> wrote:

> It seems that although require normally makes sure a certain files only
> gets included once require somehow doesn't take into account the file
> the interpreter first included.


Exactly, but should this be the case?

Cheers,
Zev



 
Reply With Quote
 
Gennady Bystritsky
Guest
Posts: n/a
 
      02-19-2005

On Feb 18, 2005, at 4:59 AM, Zev Blut wrote:

> On Fri, 18 Feb 2005 21:09:47 +0900, Nospam
> <(E-Mail Removed)-nonsense.org> wrote:
>
>> It seems that although require normally makes sure a certain files
>> only gets included once require somehow doesn't take into account the
>> file the interpreter first included.

>
> Exactly, but should this be the case?


require provides a simple mechanism trying to prevent multiple file
loads -- it keeps loaded file paths in array $" just as given
(appending a proper extension - .rb, .so, etc. - if it is missing) and
does not load a file if the same path is already present in the array.
It is very easy to trick it by requiring the same file using different
paths, like in "test.rb", "./test.rb", "././test.rb".

In general, it is very hard and time consuming to determine that
different paths refer to the same file, so require does not even try to
pretend that it is robust.

Knowing how require works, you can easily implement some work around
for your particular case.

>
> Cheers,
> Zev
>
>
>


Sincerely,
Gennady Bystritsky



 
Reply With Quote
 
Zev Blut
Guest
Posts: n/a
 
      02-21-2005
Hello,

On Sat, 19 Feb 2005 15:19:59 +0900, Gennady Bystritsky <(E-Mail Removed)>
wrote:

> In general, it is very hard and time consuming to determine that
> different paths refer to the same file, so require does not even try to
> pretend that it is robust.


It certainly appears to be a bit tricky. Although, it would be nice
if the executed program was added to $" so that it could prevent being
required again.


> Knowing how require works, you can easily implement some work around for
> your particular case.


The solution for the day is probably that my colleagues and I need to
make all executable programs thin wrappers that only require the main
code and implement the __FILE__ == $0 logic.

Best,
Zev


 
Reply With Quote
 
Martin Ankerl
Guest
Posts: n/a
 
      02-21-2005
> In general, it is very hard and time consuming to determine that
> different paths refer to the same file, so require does not even try to
> pretend that it is robust.


Why not calculate a hash of the file and use this in the check. This
would make the whole thing independent from the actual path, and allows
to re-require a file if its content changes.

martinus



 
Reply With Quote
 
Zev Blut
Guest
Posts: n/a
 
      02-21-2005
On Mon, 21 Feb 2005 20:00:37 +0900, Martin Ankerl
<(E-Mail Removed)> wrote:

>> In general, it is very hard and time consuming to determine that
>> different paths refer to the same file, so require does not even try to
>> pretend that it is robust.

>
> Why not calculate a hash of the file and use this in the check. This
> would make the whole thing independent from the actual path, and allows
> to re-require a file if its content changes.


Interesting solution! Although, I am sure some people may not like the
potential performance hit. Also the re-require could be good and it
could be bad, depending upon various situations.

A coworker of mine just commented why not just use File.expand_path for
the required file? Is there any reason not to do this?

Cheers,
Zev





 
Reply With Quote
 
Joel VanderWerf
Guest
Posts: n/a
 
      02-21-2005
Zev Blut wrote:
> A coworker of mine just commented why not just use File.expand_path for
> the required file? Is there any reason not to do this?


Symlinks...

$ cd /tmp
$ touch foo
$ ln -s foo bar
$ ruby -e 'p File.expand_path("foo")'
"/tmp/foo"
$ ruby -e 'p File.expand_path("bar")'
"/tmp/bar"

It might not be very portable, but there is File::Stat#ino:

$ ruby -e 'p File.stat("foo").ino'
1239183
$ ruby -e 'p File.stat("foo").dev'
776
$ ruby -e 'p File.stat("bar").ino'
1239183
$ ruby -e 'p File.stat("bar").dev'
776


 
Reply With Quote
 
Zev Blut
Guest
Posts: n/a
 
      02-22-2005
On Tue, 22 Feb 2005 04:42:03 +0900, Joel VanderWerf
<(E-Mail Removed)> wrote:

> Zev Blut wrote:
>> A coworker of mine just commented why not just use File.expand_path for
>> the required file? Is there any reason not to do this?

>
> Symlinks...
>
> $ cd /tmp
> $ touch foo
> $ ln -s foo bar
> $ ruby -e 'p File.expand_path("foo")'
> "/tmp/foo"
> $ ruby -e 'p File.expand_path("bar")'
> "/tmp/bar"


Yes that is true, but I noticed if you actually go to directory with
a symlink, it will expand to the true path. Like so:

$ cd /tmp/
$ mkdir foo
$ ln -s foo bar
$ touch foo/baz.rb
$ ruby -e 'Dir.chdir("foo") ;p File.expand_path("baz.rb")'
"/tmp/foo/baz.rb"
$ ruby -e 'Dir.chdir("bar") ;p File.expand_path("baz.rb")'
"/tmp/foo/baz.rb"

Is this portable or are there other problems with doing it this way?

Best,
Zev


 
Reply With Quote
 
Joel VanderWerf
Guest
Posts: n/a
 
      02-22-2005
Zev Blut wrote:
> On Tue, 22 Feb 2005 04:42:03 +0900, Joel VanderWerf
> <(E-Mail Removed)> wrote:
>
>> Zev Blut wrote:
>>
>>> A coworker of mine just commented why not just use File.expand_path for
>>> the required file? Is there any reason not to do this?

>>
>>
>> Symlinks...
>>
>> $ cd /tmp
>> $ touch foo
>> $ ln -s foo bar
>> $ ruby -e 'p File.expand_path("foo")'
>> "/tmp/foo"
>> $ ruby -e 'p File.expand_path("bar")'
>> "/tmp/bar"

>
>
> Yes that is true, but I noticed if you actually go to directory with
> a symlink, it will expand to the true path. Like so:
>
> $ cd /tmp/
> $ mkdir foo
> $ ln -s foo bar
> $ touch foo/baz.rb
> $ ruby -e 'Dir.chdir("foo") ;p File.expand_path("baz.rb")'
> "/tmp/foo/baz.rb"
> $ ruby -e 'Dir.chdir("bar") ;p File.expand_path("baz.rb")'
> "/tmp/foo/baz.rb"
>
> Is this portable or are there other problems with doing it this way?


Hm, I didn't expect that. And also:

$ ruby -e 'Dir.chdir("bar") ;p Dir.pwd'
"/tmp/foo"

In the shell (using linux, zsh) it works differently:

$ cd bar
$ pwd
/tmp/bar

Another data point:

$ ruby -e 'Dir.chdir("bar"); puts `pwd`'
/tmp/foo

I guess ruby follows symlinks when doing Dir.chdir?

Anyway, it doesn't solve the problem of a symlinked .rb file, if that's
a problem.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to require Ruby 1.9 from a required file? Sarah Allen Ruby 3 09-08-2010 01:52 AM
InteractiveConsole executed in another thread. Germán Diago Python 0 10-20-2009 10:02 AM
detect if required or executed? I. E. Smith-Heisters Ruby 4 06-17-2008 09:30 PM
Which way is the best way to require another file in .rb Eddy Xu Ruby 5 04-11-2008 06:25 PM
How to use several separate classes (separate files) to be executed in one class (another file) EvgueniB Java 1 12-15-2003 01:18 AM



Advertisments