192

I've one file, main.rb with the following content:

require "tokenizer.rb"

The tokenizer.rb file is in the same directory and its content is:

class Tokenizer
    def self.tokenize(string)
        return string.split(" ")
    end
end

If i try to run main.rb I get the following error:

C:\Documents and Settings\my\src\folder>ruby main.rb

C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- tokenizer.rb (LoadError)
        from C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require '
        from main.rb:1:in `<main>'

I just noticed that if I use load instead of require everything works fine. What may the problem be here?

Holger Just
  • 52,918
  • 14
  • 115
  • 123
The Coding Monk
  • 7,684
  • 12
  • 41
  • 56

13 Answers13

208

I just tried and it works with require "./tokenizer".

starball
  • 20,030
  • 7
  • 43
  • 238
Pascal
  • 2,709
  • 1
  • 19
  • 17
204

Just do this:

require_relative 'tokenizer'

If you put this in a Ruby file that is in the same directory as tokenizer.rb, it will work fine no matter what your current working directory (CWD) is.

Explanation of why this is the best way

The other answers claim you should use require './tokenizer', but that is the wrong answer, because it will only work if you run your Ruby process in the same directory that tokenizer.rb is in. Pretty much the only reason to consider using require like that would be if you need to support Ruby 1.8, which doesn't have require_relative.

The require './tokenizer' answer might work for you today, but it unnecessarily limits the ways in which you can run your Ruby code. Tomorrow, if you want to move your files to a different directory, or just want to start your Ruby process from a different directory, you'll have to rethink all of those require statements.

Using require to access files that are on the load path is a fine thing and Ruby gems do it all the time. But you shouldn't start the argument to require with a . unless you are doing something very special and know what you are doing.

When you write code that makes assumptions about its environment, you should think carefully about what assumptions to make. In this case, there are up to three different ways to require the tokenizer file, and each makes a different assumption:

  1. require_relative 'path/to/tokenizer': Assumes that the relative path between the two Ruby source files will stay the same.
  2. require 'path/to/tokenizer': Assumes that path/to/tokenizer is inside one of the directories on the load path ($LOAD_PATH). This generally requires extra setup, since you have to add something to the load path.
  3. require './path/to/tokenizer': Assumes that the relative path from the Ruby process's current working directory to tokenizer.rb is going to stay the same.

I think that for most people and most situations, the assumptions made in options #1 and #2 are more likely to hold true over time.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Can you please tell is the meaning of this ? What does it do behind the scenes ? Thanks. – sid smith Sep 21 '14 at 08:22
  • There's not much to know. Here's the [documentation](http://ruby-doc.org/core/Kernel.html#method-i-require_relative) and the [source code](https://github.com/ruby/ruby/blob/eeb05e8c119f8cab6434d90f21551b6bb2954778/load.c#L820-L837) for require_relative. – David Grayson Sep 21 '14 at 08:48
  • This answer is great, not just because of the answer, but because of the crystal clear explanation. – BenKoshy Oct 18 '22 at 23:42
99

Ruby 1.9 has removed the current directory from the load path, and so you will need to do a relative require on this file, as David Grayson says:

require_relative 'tokenizer'

There's no need to suffix it with .rb, as Ruby's smart enough to know that's what you mean anyway.

notapatch
  • 6,569
  • 6
  • 41
  • 45
Ryan Bigg
  • 106,965
  • 23
  • 235
  • 261
  • 3
    This assumes that the CWD is the directory that the scripts are stored in. – David Grayson Mar 17 '12 at 14:27
  • @RyanBigg - I am new to ruby. Can you please explain what this means - `Ruby 1.9 has removed the current directory from the load path` ? What is this current directory and load path ? Thanks. – sid smith Sep 21 '14 at 08:20
  • What am I supposed to read in the OP? Just because the OP happened to have the CWD equal to the directory with the scripts doesn't mean it's always going to be that way, so I like to push for a more robust solution like using `require_relative`. Tomorrow he might type `cd ..` and then `ruby folder/main.rb` and be sad your solution doesn't work anymore. I don't think that using `require` has any benefit here. – David Grayson Sep 21 '14 at 09:20
  • 1
    Updated for `require_relative` (which didn't exist, or I didn't know about it, at the time of posting) – Ryan Bigg Sep 23 '14 at 02:16
  • yeah... so unless you are using ruby 1.8.7 or earlier ( :O ) there is absolutely no reason not to use require_relative. this is the way to do it – Mircea Mar 20 '15 at 16:22
37

require loads a file from the $LOAD_PATH. If you want to require a file relative to the currently executing file instead of from the $LOAD_PATH, use require_relative.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
14

I would recommend,

load './tokenizer.rb'

Given, that you know the file is in the same working directory.

If you're trying to require it relative to the file, you can use

require_relative 'tokenizer'

I hope this helps.

13

Another nice little method is to include the current directory in your load path with

$:.unshift('.')

You could push it onto the $: ($LOAD_PATH) array but unshift will force it to load your current working directory before the rest of the load path.

Once you've added your current directory in your load path you don't need to keep specifying

 require './tokenizer' 

and can just go back to using

require 'tokenizer'
Pseudomonkey
  • 143
  • 1
  • 7
9

This will work nicely if it is in a gem lib directory and this is the tokenizer.rb

require_relative 'tokenizer/main'
brian d foy
  • 129,424
  • 31
  • 207
  • 592
Douglas G. Allen
  • 2,203
  • 21
  • 20
3

For those who are absolutely sure their relative path is correct, my problem was that my files did not have the .rb extension! (Even though I used RubyMine to create the files and selected that they were Ruby files on creation.)

Double check the file extensions on your file!

Mamun
  • 66,969
  • 9
  • 47
  • 59
2

What about including the current directory in the search path?

ruby -I. main.rb
Hans-J. Schmid
  • 303
  • 2
  • 7
1

I used jruby-1.7.4 to compile my ruby code.

require 'roman-numerals.rb' 

is the code which threw the below error.

LoadError: no such file to load -- roman-numerals
  require at org/jruby/RubyKernel.java:1054
  require at /Users/amanoharan/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:36
   (root) at /Users/amanoharan/Documents/Aptana Studio 3 Workspace/RubyApplication/RubyApplication1/Ruby2.rb:2

I removed rb from require and gave

require 'roman-numerals' 

It worked fine.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
0

First :

$ sudo gem install colored2

And,you should input your password

Then :

$ sudo gem update --system  

Appear Updating rubygems-update ERROR: While executing gem ... (OpenSSL::SSL::SSLError) hostname "gems.ruby-china.org" does not match the server certificate

Then:

$  rvm -v
$ rvm get head

Last What language do you want to use?? [ Swift / ObjC ]

ObjC

Would you like to include a demo application with your library? [ Yes / No ]

Yes

Which testing frameworks will you use? [ Specta / Kiwi / None ]

None

Would you like to do view based testing? [ Yes / No ]

No

What is your class prefix?

XMG

Running pod install on your new library.

Thomas Rollet
  • 1,573
  • 4
  • 19
  • 33
0

The problem is that require does not load from the current directory. This is what I thought, too but then I found this thread. For example I tried the following code:

irb> f = File.new('blabla.rb')
=> #<File:blabla.rb>
irb> f.read
=> "class Tokenizer\n    def self.tokenize(string)\n        return string.split(
\" \")\n    end\nend\n"
irb> require f
LoadError: cannot load such file -- blabla.rb
        from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
        from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
        from (irb):24
        from D:/dev/Ruby193/bin/irb:12:in `<main>'

As it can be seen it read the file ok, but I could not require it (the path was not recognized). and here goes code that works:

irb f = File.new('D://blabla.rb')
=> #<File:D://blabla.rb>
irb f.read
=> "class Tokenizer\n    def self.tokenize(string)\n        return string.split(
\" \")\n    end\nend\n"
irb> require f
=> true

As you can see if you specify the full path the file loads correctly.

Community
  • 1
  • 1
Boris Strandjev
  • 46,145
  • 15
  • 108
  • 135
  • 1
    It is a matter of choice. I personally always like to test what I am doing in interactive console. I make quite many mistakes, and I like getting interactive feedback. – Boris Strandjev Mar 17 '12 at 14:30
-2

you need to give the path. Atleast you should give the path from the current directory. It will work for sure. ./filename