Reputation: 3535
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. require
s like this: ./file
work fine, but require
s 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:in
require' 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: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 /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: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 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
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
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