Sinatra でスペック ファイルを要求する簡単な方法
概要
次のような 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
解決策
max pleaner の答えについての説明…
書くとき:
require 'lib/house_distributer.rb'
Ruby は、環境変数に割り当てられたディレクトリ内でファイルを検索します。は文字列の配列であり、各文字列はディレクトリへのパスです。配列内のディレクトリが順番に検索され、最初に一致したものが優先されます。
というディレクトリが含まれている場合:
'/Users/7stud/ruby_programs'
次に、上記の require ステートメントは絶対パスを持つファイルを検索します。
'/Users/7stud/ruby_programs/lib/house_distributer.rb'
次のようにして、どのディレクトリがディレクトリにあるかを確認できます。
$ 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 は現在の作業ディレクトリを基準にしてファイルを探します。ただし、現在の作業ディレクトリは、require ステートメントを含むファイルを含むディレクトリではない可能性があることに注意してください。たとえば、sinatra プログラムを別のディレクトリ (require ステートメントを含むファイルから 2 レベル上) から実行する場合、2 レベル上のディレクトリが現在の作業ディレクトリとなり、ruby はそのディレクトリを基準にして必要なファイルを検索します。 2 レベル上のディレクトリ。
「require_relative」と入力します。 require_relative は、現在の作業ディレクトリではなく、現在のファイルのパスに相対してファイルを検索します。
そのため、相対パスを指定した require は決して使用せず、代わりに require_relative を使用する必要があります。
いつでもプログラムでパスを追加できることに注意してください。
$LOAD_PATH << '/Users/7stud/ruby_programs'
そして、そのディレクトリに Dog.rb というファイルがある場合は、次のように要求できます。
require 'dog' #extension is unnecessary
コメントへの返信:
最も簡単なことは次のようになります。
$LOAD_PATH << "/Users/jwan/Desktop/programming/interview_questions/gemini/jobcoin_mixer/"
ただし、sinatra では、settings.root はアプリ ディレクトリへのパスであるため、次のようにします。
$LOAD_PATH.unshift settings.root
そうすれば、何も変更せずにアプリを別のディレクトリに移動できます。
または、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"]