本文介绍require, require_relative, load, autoload(遇到再介绍)
参考文献:The require and load path in Ruby
require
1.根据ruby api的介绍,require "xx", 如果xx是绝对目录,则加载绝路路径的文件,这个没有任何歧义。但是如果xx是相对路径(一般都是相对路径),则系统会从$LOAD_PATH(别称是$:)中寻找文件夹目录。
#rails项目中TestDemo/test/model/article_test.rb
require 'test_helper'
class ArticleTest < ActiveSupport::TestCase
test "the truth" do
puts $:
assert true
end
end
#puts $:结果如下
/Users/jayzen/workshop/test_demo/lib
/Users/jayzen/workshop/test_demo/vendor
/Users/jayzen/workshop/test_demo/app/assets
/Users/jayzen/workshop/test_demo/app/channels
/Users/jayzen/workshop/test_demo/app/controllers
/Users/jayzen/workshop/test_demo/app/controllers/concerns
/Users/jayzen/workshop/test_demo/app/helpers
/Users/jayzen/workshop/test_demo/app/jobs
/Users/jayzen/workshop/test_demo/app/mailers
/Users/jayzen/workshop/test_demo/app/models
/Users/jayzen/workshop/test_demo/app/models/concerns
/Users/jayzen/.rvm/gems/ruby-2.4.0/gems/turbolinks-5.0.1/lib
...中间省略内容
/Users/jayzen/workshop/test_demo/test
./Users/jayzen/workshop/test_demo/lib
/Users/jayzen/workshop/test_demo/vendor
/Users/jayzen/workshop/test_demo/app/assets
/Users/jayzen/workshop/test_demo/app/channels
/Users/jayzen/workshop/test_demo/app/controllers
/Users/jayzen/workshop/test_demo/app/controllers/concerns
/Users/jayzen/workshop/test_demo/app/helpers
/Users/jayzen/workshop/test_demo/app/jobs
/Users/jayzen/workshop/test_demo/app/mailers
/Users/jayzen/workshop/test_demo/app/models
/Users/jayzen/workshop/test_demo/app/models/concerns
/Users/jayzen/workshop/test_demo/test #可以看到这里,test_helper.rb文件在这个目录中,所以require 'test_helper'可以成功
2.这里说明如何添加到$LOAD_PATH中
#test文件夹下面,有a.rb和b.rb文件
#a.rb
puts "a"
#b.rb
require "a"
#test文件夹下面,执行ruby b.rb,出现 LoadError错误
#解决方式如下所示:
#1.最直接的解决方式 $: << "/Users/jayzen/workshop/test"
#2.通用的解决方式
#b.rb
folder = File.expand_path('.',__dir__)
#$LOAD_PATH = File.expand_path('../track/lib',__FILE__)
$:.unshift(folder) unless $:.include?(folder)
require 'a'
3.require中可以使用不需要$LOAD_PATH的相对路径
#test文件夹下面,有a.rb和b.rb文件
#a.rb
puts "a"
#b.rb
require "./a"
#test文件夹下面,执行ruby b.rb#=> a, 正确
#但是在test文件夹的父文件夹中执行b.rb文件
#test的父文件夹中执行,执行ruby test/b.rb #=> LoadError,因此在require中使用相对路径是不合适的
#错误原因解释
上面的“.”号指向的是ruby进程的当前工作目录,而不是源文件的目录
test文件夹执行b.rb文件,ruby进程的当前工作目录是~/workshop/test
workshop文件夹执行b.rb文件,ruby进程的当前工作目录是~/workshop
require_relative
#上面的require "./a"中使用require的相对路径,为了克服这个文艺,可以使用require_relative
#test文件夹下面存在a.rb和b.rb
#a.rb
puts "a"
#b.rb
require_relative "./a"
#执行结果
test文件夹下面,ruby b.rb #=>a
workshop文件夹下面,ruby test/b.rb #=>a
#结论
require中的"."指向的ruby进程的当前工作目录,而require_relative指向的是当前文件所在的文件夹
load
#代码示例,redflag.rb和test_events.rb文件在test文件夹下面
#redflag.rb
def event(name)
puts "ALTER: #{name}" if yield
end
Dir.glob("*events.rb").each{ |file| load file}
#test_events.rb
event "an event that always happens" do
true
end
event "an event that never happens" do
false
end
#执行代码
在test文件夹下面,执行redflag.rb文件,会得到预期的结果,但是在test文件夹的父文件夹下面执行则报错
load和require的对比
#相同点
1.文件加载方式一致,包括绝对路径直接加载,相对路径到$:中加载
#不同点
1.load "file" #默认是“./file”,在当前文件夹下面执行代码会从当前文件夹中寻找文件,其次是从$:从寻找文件,而且“.”默认是
指向的ruby进程的当前工作目录。require "file" #直接从$:中寻找文件。
2.require文件只能加载一次,而load文件可以反复被加载
irb# require "nokogiri" #=>true
irb# require "nokogiri" #=>false, require第二次加载出现错误
3.require可以不用加后缀,load需要添加后缀