本文介绍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需要添加后缀

results matching ""

    No results matching ""