Search code examples
rubyrubygemsirbpryfileutils

Requiring ruby gems giving mixed results


Noticed today that running require fileutils in pry always returns false. But, if I do the same thing in irb, it returns true. Furthermore, when fileutils is set to false, it still works!

First I thought that fileutils is a dependency of pry, and that would explain why it is already required. But it's not. Am I missing something fundamental here?

[07:40] ~/Desktop $ gem dependency pry
Gem pry-0.10.2
  bundler (~> 1.0, development)
  coderay (~> 1.1.0)
  method_source (~> 0.8.1)
  slop (~> 3.4)

Gem pry-theme-1.1.3
  bundler (~> 1.0, development)
  coderay (~> 1.1)
  json (~> 1.8)

Example:

First I use pry to make some folders. Is fileutils already loaded? Notice that even though fileutils returns false it still works:

[07:44] ~/Desktop $ ls
[07:44] ~/Desktop $    ########## (nothing)
[07:44] ~/Desktop $ pry
[1] pry(main)> require 'fileutils'
=> false
[2] pry(main)> FileUtils::mkdir_p 'foo'
=> ["foo"]
[3] pry(main)> Dir.mkdir('bar')
=> 0
[4] pry(main)> Dir["/home/caveman/Desktop/*"]
=> ["/home/caveman/Desktop/foo", "/home/caveman/Desktop/bar"]

I remove the folders I just created...

[07:48] ~/Desktop $ rm -r *
[07:48] ~/Desktop $ ls
[07:48] ~/Desktop $    ########## (nothing again)

Now I try again with irb:

[07:49] ~/Desktop $ irb
irb(main):001:0> require 'fileutils'
=> true
irb(main):002:0> FileUtils::mkdir_p 'foo2'
=> ["foo2"]
irb(main):003:0> Dir.mkdir 'bar2'
=> 0
irb(main):004:0> Dir["/home/caveman/Desktop/*"]
=> ["/home/caveman/Desktop/bar2", "/home/caveman/Desktop/foo2"]

Here's what blows my mind. Even after I set 'fileutils' to false in irb, it still works:

irb(main):005:0> require 'fileutils'
=> false
irb(main):006:0> FileUtils::mkdir_p 'foo3'
=> ["foo3"]
irb(main):007:0> Dir["/home/caveman/Desktop/*"]
=> ["/home/caveman/Desktop/foo3", "/home/caveman/Desktop/bar2", "/home/caveman/Desktop/foo2"]

Solution

  • First off, FileUtils isn't a gem, so it will never show up as a gem dependency.

    Secondly, the return value of require doesn't tell you whether requiring succeeded or not (if it fails, it will raise an exception). false just means it's already loaded. Your statement

    Even after I set 'fileutils' to false in irb

    doesn't make sense. You're not setting anything at all, you're just calling require again and the second time it returns false.

    What you've observed just means that pry (or one of its dependencies) either loads FileUtils directly or loads a bit of the standard library that loads FileUtils. It looks like pry requires 'tempfile', which itself requires 'tmpdir' which in turn requires 'fileutils'.