I have a spec_helper
that looks like this:
require 'pry'
require 'helpers/data_helper.rb'
require 'distributer.rb'
require 'house_distributer.rb'
require 'accounting_service.rb'
require 'mixer_worker.rb'
require 'mixer.rb'
require 'transaction_service.rb'
ENV['RACK_ENV'] = 'test'
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.warnings = true
config.order = :random
end
and a folder structure that looks like this:
.
├── Gemfile
├── Gemfile.lock
├── README.md
├── app.rb
├── config.ru
├── lib
│ ├── accounting_service.rb
│ ├── distributer.rb
│ ├── house_distributer.rb
│ ├── mixer.rb
│ ├── mixer_worker.rb
│ └── transaction_service.rb
├── public
│ ├── css
│ │ └── add_coins.css
│ ├── images
│ │ └── bitcoin_dawg.jpg
│ └── javascripts
│ └── add_coins.js
├── spec
│ ├── helpers
│ │ └── data_helper.rb
│ ├── lib
│ │ ├── accounting_service_spec.rb
│ │ └── transaction_service_spec.rb
│ └── spec_helper.rb
└── views
└── add_coins.erb
This does not work:
Dir["lib/*.rb"].each {|file| require file }
[1] pry(main)> Dir["lib/*.rb"]
=> ["lib/house_distributer.rb", "lib/distributer.rb", "lib/mixer.rb", "lib/accounting_service.rb", "lib/mixer_worker.rb", "lib/transaction_service.rb"]
I get this error message:
/Users/jwan/.rbenv/versions/2.1.2/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- lib/house_distributer.rb (LoadError)
from /Users/jwan/.rbenv/versions/2.1.2/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
What can I do to make this easier?
Also side note, distributer.rb
has to be loaded before house_distributer.rb
because of this:
class HouseDistributer < Distributer
end
Some explanation of max pleaner's answer...
When you write:
require 'lib/house_distributer.rb'
ruby looks for the file in the directories assigned to the $LOAD_PATH
environment variable. $LOAD_PATH
is an array of Strings, where each String is a path to a directory. The directories in the $LOAD_PATH array are searched in order, and the first match wins.
If $LOAD_PATH
contains a directory called:
'/Users/7stud/ruby_programs'
Then the require
statement above will look for a file with the absolute path:
'/Users/7stud/ruby_programs/lib/house_distributer.rb'
You can check which directories are in your $LOAD_PATH
like this:
$ puts $LOAD_PATH
This is what I get:
/Users/7stud/.rvm/gems/ruby-2.4.0@global/gems/did_you_mean-1.1.0/lib
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/x86_64-darwin14
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/vendor_ruby/2.4.0
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/vendor_ruby/2.4.0/x86_64-darwin14
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/vendor_ruby
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0
/Users/7stud/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/x86_64-darwin14
Obviously, your app's files are not in directories like those.
On the other hand, if you require
a file whose path starts with a /
or a .
-- for instance:
require './lib/house_distributer.rb'
then ruby skips $LOAD_PATH
, and in this case ruby looks for the file relative to the current working directory. Note however, that the current working directory may not be the directory containing the file with the require statement. For instance, if you execute your sinatra program from a different directory, say two levels up from the file containing the require
statement, then the two levels up directory will be the current working directory, and ruby will look for the required file relative to the two levels up directory.
Enter require_relative
. require_relative
will look for the file relative to the path of the current file--not the current working directory.
As a result, you should probably never use require
with a relative path and instead use require_relative
.
Note that you can also programmatically add paths to $LOAD_PATH any time you want:
$LOAD_PATH << '/Users/7stud/ruby_programs'
And if a file called dog.rb is
in that directory, I can require it like so:
require 'dog' #extension is unnecessary
Response to comment:
The simplest thing to do would be:
$LOAD_PATH << "/Users/jwan/Desktop/programming/interview_questions/gemini/jobcoin_mixer/"
But in sinatra, settings.root
is the path to your app directory, so do:
$LOAD_PATH.unshift settings.root
That way you can move your app to another directory without changing anything.
Or, you can remove lib/
from the front of every path that Dir[]
returned:
require 'pathname'
paths = [
"lib/house_distributer.rb",
"lib/distributer.rb",
"lib/mixer.rb",
"lib/accounting_service.rb",
]
new_paths = paths.map do |path|
pn = Pathname.new path
pn.relative_path_from(pn.parent).to_s
end
p new_paths
--output:--
["house_distributer.rb", "distributer.rb", "mixer.rb", "accounting_service.rb"]