Ruby 在Sinatra中更方便地要求规范文件
我有一个Ruby 在Sinatra中更方便地要求规范文件,ruby,sinatra,Ruby,Sinatra,我有一个spec\u助手,看起来像这样: 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']
spec\u助手
,看起来像这样:
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
$ puts $LOAD_PATH
文件夹结构如下所示:
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
$ puts $LOAD_PATH
这不起作用:
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\u distributer.rb
之前加载,因为:
class HouseDistributer < Distributer
end
class-housedributer
找不到文件是因为您使用了“lib/*.rb”
而不是/“lib/*.rb”
要确保以正确的顺序加载依赖项,可以执行以下操作:
lib/distributor/house\u distributor.rb
Dir['./lib/**/*.rb']
.sort_by { |path| path.count("/") }
.each { |path| require path }
这将使用***.rb
进行递归搜索,并在需要之前按“/”计数(其深度)对文件进行排序require 'lib/house_distributer.rb'
ruby在分配给$LOAD\u PATH
环境变量的目录中查找该文件$LOAD_PATH
是一个字符串数组,其中每个字符串都是指向目录的路径。$LOAD_PATH数组中的目录按顺序搜索,第一个匹配项获胜
如果$LOAD\u PATH
包含一个名为:
'/Users/7stud/ruby_programs'
然后,上面的require
语句将查找具有绝对路径的文件:
'/Users/7stud/ruby_programs/lib/house_distributer.rb'
您可以像下面这样检查$LOAD\u路径中的目录:
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
$ 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 './lib/house_distributer.rb'
然后ruby跳过$LOAD\u PATH
,在本例中,ruby查找相对于当前工作目录的文件。但是请注意,当前工作目录可能不是包含带有require语句的文件的目录。例如,如果您从不同的目录执行sinatra程序,比如从包含require
语句的文件向上两级执行,那么向上两级的目录将是当前工作目录,ruby将查找相对于向上两级目录的所需文件
输入require\u relative
require_relative
将查找相对于当前文件路径的文件,而不是当前工作目录
因此,您可能永远不应该使用带有相对路径的require
,而应该使用require\u relative
请注意,您还可以随时以编程方式将路径添加到$LOAD_PATH:
$LOAD_PATH << '/Users/7stud/ruby_programs'
对评论的回应:
最简单的做法是:
$LOAD_PATH << "/Users/jwan/Desktop/programming/interview_questions/gemini/jobcoin_mixer/"
这样,您就可以将应用程序移动到另一个目录,而无需更改任何内容
或者,您可以从Dir[]
返回的每个路径的前面删除lib/
:
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"]
另外两个答案在技术上是正确的,并且针对的是目标,而不是目标。换句话说-首先你为什么要这样做?例如,为什么要这样做:
另请注意,distributer.rb必须在house_distributer.rb之前加载,因为:
class HouseDistributer < Distributer
end
由于transaction\u service.rb
似乎需要housedributer
来自lib/housedributer.rb
# lib/transaction_service.rb
require_relative "house_distributer.rb"
经验法则
如果一个文件需要另一个文件来运行,则require
(或require\u relative
)将它放在需要它的文件中。然后你会得到:
- 一种只运行所需内容的自然沙箱(可能Distributer工作正常,而HouseDistributer由于一个猴子补丁而出现错误-您如何知道您是否需要实际不需要的文件?)
- 不需要处理其他地方的需求
- 不需要(或更少需要)知道需求的顺序
- 无需摆弄加载路径(自从引入
require\u relative
以来,这一直是一个可疑的需求)
- 更改加载路径,然后使用
require
可以破坏沙箱,并使规范正常工作,如果加载您已安装在系统上但在gempec中未定义为依赖项的gem,则可能会失败
我想补充一点,也使用bundler的沙箱,以避免进一步的错误,并让它处理您的加载路径,例如
bundle安装--binstubs--path=vendor
(或Mac上的vendor.noindex),然后:
<代码> bin /rSPEC< /COD>以及您需要的命令行ARG。
以后,考虑使用<代码>树>代码>获取目录结构的文本版本,而不是使用屏幕树什么是“树”?我如何使用它@maxpleanertree
是一个unix命令。查看以查看输出的外观,然后安装树。或者,如果您安装了自制软件,那么它就非常简单:brew安装树
。我编辑了我的帖子,感谢您的推荐!试试:tree`pwd`
——这将获得要打印的顶级目录。或者做cd..
然后tree-app
虽然对于新手用户来说更容易混淆,但通常更习惯于动态地更改$LOAD\u路径。例如:$LOAD\u PATH.unshift(File.expand\u PATH(File.dirname(\uu File\uuu))
或者像许多gem一样$:.push File.expand\u PATH(“../lib”,\uu File\uuuu)
我想我的问题是Sinatra在加载路径中查找文件,其中包括:“/Users/jwan/Desktop/programming/interview\u questions/gemini/jobcoin\u mixer/lib”
因此它找不到名为'lib/something.rb'的文件。我怎样才能去掉那个多余的库?@Jwan622,看我答案的底部。@Jwan622,这是怎么回事