我有一个
spec_helper
,看起来像这样:
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
文件夹结构如下所示:
.
├── 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
这不起作用:
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"]
我收到此错误消息:
/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'
我该怎么做才能让这件事变得更容易?
另外注意,
distributer.rb
必须在house_distributer.rb
之前加载,因为:
class HouseDistributer < Distributer
end
maxplener的回答的一些解释...
当你写下:
require 'lib/house_distributer.rb'
ruby 在分配给
$LOAD_PATH
环境变量的目录中查找文件。 $LOAD_PATH
是一个字符串数组,其中每个字符串都是一个目录的路径。按顺序搜索 $LOAD_PATH 数组中的目录,第一个匹配的获胜。
如果
$LOAD_PATH
包含一个名为: 的目录
'/Users/7stud/ruby_programs'
然后上面的
require
语句会寻找绝对路径的文件:
'/Users/7stud/ruby_programs/lib/house_distributer.rb'
您可以像这样检查您的
$LOAD_PATH
中有哪些目录:
$ puts $LOAD_PATH
这就是我得到的:
/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
显然,您的应用程序的文件不在这样的目录中。
另一方面,如果您
require
路径以 /
或 .
开头的文件 - 例如:
require './lib/house_distributer.rb'
然后 ruby 会跳过
$LOAD_PATH
,在这种情况下,ruby 会查找相对于 当前工作目录 的文件。但请注意,“当前工作目录”可能不是包含带有 require 语句的文件的目录。例如,如果您从不同的目录执行 sinatra 程序,假设从包含 require
语句的文件向上两级,那么上两级目录将是 当前工作目录,并且 ruby 将查找所需的相对于上两级目录的文件。 输入
require_relative
。
require_relative
将查找相对于当前文件路径的文件,而不是当前工作目录。因此,您可能永远不应该将 require
与相对路径一起使用,而应使用
require_relative
。请注意,您还可以随时以编程方式将路径添加到 $LOAD_PATH:
$LOAD_PATH << '/Users/7stud/ruby_programs'
如果该目录中有一个名为
dog.rb is
的文件,我可以像这样要求它:
require 'dog' #extension is unnecessary
回复评论: 最简单的事情是:
$LOAD_PATH << "/Users/jwan/Desktop/programming/interview_questions/gemini/jobcoin_mixer/"
但是在 sinatra 中,
settings.root
是你的应用程序目录的路径,所以这样做:
$LOAD_PATH.unshift settings.root
这样您就可以将应用程序移动到另一个目录而无需更改任何内容。
或者,您可以从
lib/
返回的每条路径的前面删除
Dir[]
: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"]
"lib/*.rb"
而不是
./"lib/*.rb"
。为了确保依赖项以正确的顺序加载,您可以这样做:
lib/distributor/house_distributor.rb
Dir['./lib/**/*.rb']
.sort_by { |path| path.count("/") }
.each { |path| require path }
这使用
**/*.rb
进行递归搜索,并在需要之前按“/”(其深度)的数量对文件进行排序
,但不是目标。换句话说 - 你为什么要这样做? 例如,为什么这样做:
另外注意,distribuner.rb 必须在 house_distributer.rb 之前加载,因为:
class HouseDistributer < Distributer end
不是这个吗?
require_relative "distributer.rb"
class HouseDistributer < Distributer
end
在测试中(咳嗽
)抱歉,规格:
# spec/house_distributer_spec.rb
require 'spec_helper'
require_relative "../lib/house_distributer.rb"
# spec/transaction_service_spec.rb
require 'spec_helper'
require_relative "../lib/transaction_service.rb"
而且由于
transaction_service.rb
似乎需要来自
HouseDistributer
的 lib/house_distributer.rb
…# lib/transaction_service.rb
require_relative "house_distributer.rb"
经验法则如果一个文件需要另一个文件来运行,则
require
(或
require_relative
)将其放在需要它的文件中。然后你会得到:一种仅运行所需内容的自然沙箱(也许 Distributer 工作正常,而 HouseDistributer 由于猴子补丁而出现错误 - 你如何知道你是否
require
require_relative
require
bundle install --binstubs --path=vendor
(或Mac上的vendor.noindex)然后:
bin/rspec
以及您需要的任何命令行参数。