Require Command Not Working Within Bash Irb on Snow Leopard

Require command not working within bash irb on Snow Leopard

This is because the working directory is no longer in the Ruby path in Ruby 1.9.2. This does work:

require './ex25'

Why isn't current directory on my Ruby path?

In Ruby 1.9.2 the Powers that Be introduced an explicit change so that the working directory is no longer in the Ruby path. I thought it was the Apocalypse and a terrible thing, until I learned about require_relative. My apps tend to look like this:

require 'some_gem'
require 'another_gem'
require_relative 'lib/init'

And then lib/init.rb can have:

require_relative 'lib1' # this is lib/lib1.rb
require_relative 'lib2' # this is lib/lib2.rb

It's the bees knees, and solves all sorts of problems I used to have with requiring the same file from different working directories.

Edit: Unfortunately (for reasons I don't know and haven't looked into) require_relative doesn't work specifically in irb. For this you can:

  1. do what you initially described: either $: << '.' or $:.unshift '.', or
  2. you can use load 'myfile.rb' or require './myfile' instead:

    irb(main):001:0> Dir['*.rb']
    => ["a.rb", "bar.rb", "foo.rb", "prime.rb", "tmp.rb"]

    irb(main):002:0> require 'a'
    LoadError: no such file to load -- a
    from <internal:lib/rubygems/custom_require>:29:in `require'
    from <internal:lib/rubygems/custom_require>:29:in `require'
    from (irb):2
    from /usr/local/bin/irb:12:in `<main>'

    irb(main):003:0> require_relative 'a'
    LoadError: cannot infer basepath
    from (irb):3:in `require_relative'
    from (irb):3
    from /usr/local/bin/irb:12:in `<main>'

    irb(main):004:0> load 'a.rb'
    a
    => true

    irb(main):005:0> require './a'
    a
    => true

loading documents on IRB ruby

It depends on the version of Ruby you are using (1.8.x or 1.9.x). load and require work both on the loadpath of Ruby. You can have a look at it by evaluating $: inside IRB. In Ruby 1.9.x the current directory is not part of the loadpath, so you have to use the absolute path to your file. Depending on the operating system you are using (Windows 7), this may look like:

c:\Users\mliebelt\Desktop>irb
irb(main):001:0> $:
=> ["C:/apps/ruby/ruby192/lib/ruby/site_ruby/1.9.1", "C:/apps/ruby/ruby192/lib/ruby/site_ruby/1.9.1/i386-msvcrt", "C:/apps/ruby/ruby192/lib/ruby/site_ruby", "C:/apps/ruby/ruby192/lib/ruby/vendor_ruby/1.9.1", "C:/apps/ruby/ruby192/lib/ruby/vendor_ruby/1.9.1/i386-msvcrt", "C:/apps/ruby/ruby192/lib/ruby/vendor_ruby", "C:/apps/ruby/ruby192/lib/ruby/1.9.1", "C:/apps/ruby/ruby192/lib/ruby/1.9.1/i386-mingw32"]
irb(main):002:0> require 'c:/Users/mliebelt/Desktop/ruby'
File c:/Users/mliebelt/Desktop/ruby.rb loaded.
=> true
irb(main):003:0> load 'c:/Users/mliebelt/Desktop/ruby.rb'
File c:/Users/mliebelt/Desktop/ruby.rb loaded.
=> true

By the way, the contents of the file ruby.rb is:

puts "File #{__FILE__} loaded."

The same session with IRB on Ruby 1.8.x may look like that:

c:\Users\mliebelt\Desktop>irb
irb(main):001:0> $:
=> ["C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby/1.8", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby/1.8/i386-msvcrt", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby/1.8", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby/1.8/i386-msvcrt", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/1.8", "C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/1.8/i386-mingw32", "."]
irb(main):002:0> require 'ruby'
File ./ruby.rb loaded.
=> true
irb(main):003:0> load 'ruby.rb'
File ./ruby.rb loaded.
=> true

The differences between require and load are:

  • require does not need the suffix (.rb) of the file

    • require 'ruby' and require 'ruby.rb' are the same
  • require reads the file into memory once, so require should normally be used instead of load, which reads the file into memory every time functions in the file are called.

So to load files (by using require or load), do the following:
- expand your load path by your current directory (if necessary). See Adding a directory to loadpath
- (when using Ruby 1.8.x) Start your program (or IRB) in the directory from which you want to load or require files.

Can you 'require' ruby file in irb session, automatically, on every command?

I usually create a simple function like this:

def reload
load 'myscript.rb'
# Load any other necessary files here ...
end

With that, a simple reload will re-import all of the scripts that I'm working on. It's not automatic, but it's the closest thing that I've been able to come up with.

You may be able to override method_missing to call this function automatically when your object is invoked with a method that doesn't exist. I've never tried it myself, though, so I can't give any specific advice. It also wouldn't help if you're calling a method that already exists but has simply been modified.

In my own laziness, I've gone as far as mapping one of the programmable buttons on my mouse to the key sequence "reload<enter>". When I'm using irb, all it takes is the twitch of a pinky finger to reload everything. Consequently when I'm not using irb, I end up with the string "reload" inserted in documents unintentionally (but that's a different problem entirely).

The command ruby does nothing on my Mac

Ruby command itself will just behave the way you said, either provide it with script file or use the -e option:

ruby -e ' puts "hello world" '

However I suspect that you want the IRB(interactive ruby). Run irb in your shell.

Ruby Include Module in IRB

That's an error in the book. The methods in Ex25 are class methods. include adds instance methods to the "current space." Remove self from the method definitions and it'll work:

module Ex25
def break_words(stuff)
stuff.split(' ')
end
end

include Ex25
break_words 'hi there' # => ["hi", "there"]

If you're curious, here's some more detail about what's going on: The place where the methods are included—the "current space"—is the Object class:

Object.included_modules  # => [Ex25, Kernel]

All Object instances gain the included methods ...

Object.new.break_words 'how are you?'  # => ["how", "are", "you?"]

... and the top-level is just an Object instance:

self.class  # => Object

But wait. If the top-level is an Object instance, why does it respond to include? Isn't include an instance method of Module (and its subclass, Class)? The answer is that the top-level has a singleton method ...

singleton_methods.include? "include"  # => true

... which we can assume forwards to the Object class.



Related Topics



Leave a reply



Submit