Denis Yakovenko
Denis Yakovenko

Reputation: 3535

Cannot require ruby files from a directory other then the one with main files (LoadError)

My problem is the following:

I can't require a ruby file from any directory other than the one with all the main files, i.e. requires like this: ./file work fine, but requires like this: dir_name/file fail.

Here's my project structure:

├── bin
│   ├── console
│   └── setup
├── CODE_OF_CONDUCT.md
├── Gemfile
├── lib
│   ├── riverbattle
│   │   ├── base.rb          <------- main file that starts everything
│   │   ├── colorful.rb
│   │   ├── computer.rb
│   │   ├── constants.rb
│   │   ├── exit_error.rb
│   │   ├── field.rb
│   │   ├── game.rb
│   │   ├── human.rb
│   │   ├── invalid_move_error.rb
│   │   ├── move.rb
│   │   ├── player.rb
│   │   ├── version.rb
│   │   └── victory_error.rb
│   └── riverbattle.rb  <------ the file from where I get the error
├── LICENSE
├── LICENSE.txt
├── Rakefile
├── README.md
├── spec
│   ├── spec_helper.rb
│   └── riverbattle_spec.rb
├── riverbattle-0.1.2.gem
└── riverbattle.gemspec

So, when I launch the app like this: ruby base.rb when I am in the lib/riverbattle/ directory, everything launches fine, but when I try to do ruby riverbattle.rb from the directory lib/, I get the following error:

➜ lib git:(master) ✗ ruby riverbattle.rb /home/denis/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in require': cannot load such file -- ./field (LoadError) from /home/denis/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:inrequire' from /home/denis/.rvm/gems/ruby-2.2.1/gems/riverbattle-0.1.2/lib/riverbattle/game.rb:1:in <top (required)>' from /home/denis/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:inrequire' from /home/denis/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in require' from /home/denis/.rvm/gems/ruby-2.2.1/gems/riverbattle-0.1.2/lib/riverbattle/base.rb:1:in ' from /home/denis/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in require' from /home/denis/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:inrequire' from riverbattle.rb:2:in `'

I just don't get it why it cannot require one single file. By the way, here's the content of the file (riverbattle.rb) from which I get the error:

require "riverbattle/version"

module Riverbattle
  require "riverbattle/base"
end

and nothing else.

I was told that require actually requires an absolute path to the file and I need to do something with my $LOAD_PATH or something, but this information doesn't help at all to solve the issue. Why is it okay to require files from the same directory, but not okay, if I require them from another one?


1) Could anybody help me with solving that problem?

2) Is it the problem with only my computer and I can safely publish it as a gem (i.e. it may work properly on another computer), or it is the wrong code that doesn't work?

Upvotes: 0

Views: 756

Answers (2)

vgoff
vgoff

Reputation: 11343

If lib/base.rb is your main file, then perhaps it should be the "executable" file? If that is the case, should it be in bin?

$LOAD_PATH can be added to by using -I option with the ruby executable.

ruby -Ipath_to_project_root/lib lib/main.rb

would then let any file that requires files in your project look in the lib folder.

It can also be used like the answer in your other question with the $: or $LOAD_PATH.

Look at how other gems are set up, and you will find that your base.rb file can live in the bin folder, just like your setup and console files are. If it is the main script that starts it all, it could be named riverbattle as is common with gems to have an executable of the same or similar name.

require is not used to load gems, it is used to load files and without any explicit path given, will look in the load path. It doesn't matter if it is a gem or not.

require_relative is used to load files that are always local relative to the file that is using the require_relative method.

Of course, the documentation is your friend.

Upvotes: 1

ndnenkov
ndnenkov

Reputation: 36110

require searches in your $LOAD_PATH. require should generally be used if you want to use a gem that is installed on your system. For your purposes you want to use require_relative:

require_relative 'riverbattle/version'

Note that at first glance

require './riverbattle/version'

might also seem to work. However, . here points to the current directory from where you run the process, not the directory where the file resides, obviously this is not what you want.

Upvotes: 3

Related Questions