在 Ruby Programming | 连载 01 - Intro and Setup 中展示了通过 rvm 安装 Ruby 的过程,安装 Ruby 不仅会安装 ruby 解释器,还安装了 Ruby 语言支持的库和文件,在使用 ruby 解释器执行代码时都能够成功找到所需要的文件或者目录。
要获取 Ruby 的安装目录位置可以在 irb 解释器中加载 rbconfig 库来获取。rbconfig 是一个接口,通过该接口可以获取 Ruby 的各种安装和配置信息。
irb --simple-prompt -r rbconfig
-r 是 require
的简写,表示用来加载 rbconfig 库,在成功加载 rbconfig 库之后就可以获取 Ruby 的各种配置信息了。
>> RbConfig::CONFIG["bindir"]
=> "/Users/maverick/.rvm/rubies/ruby-2.7.6/bin"
RbConfig::CONFIG 是一个 Hash 散列表,类似 Python 中的 Map 字典,是一种 K-V 结构的数据,根据输入的键 bindir 就可以获取相应的值。
当然 RbConfig::CONFIG 中的键值对有多个,除了 bindir 之外,还有:
RbConfig::CONFIG 的 Key | 对应的 Value 的说明 |
---|---|
rubylibdir | Ruby 标准库 |
archdir | 已编译的扩展库和文件 |
sitedir | User 自定义的第三方库和文件(Ruby 编写) |
vendordir | 安装的第三方的扩展库和文件(Ruby 编写) |
sitelibdir | User 自定义的扩展(Ruby 编写) |
sitearchdir | User 自定义的扩展(C 编写) |
irb 解释器中获取到的配置信息:
Ruby 的标准库子目录 RbConfig::CONFIG["rubylibdir"]
rubylibdir 目录中存储了 Ruby 编写的标准库文件,可以通过 require 关键字加载这些文件,常用的标准库文件如下:
仅仅使用 rubylibdir 中的提供的库就可以完成许多功能。
Ruby 的 C 扩展目录 RbConfig::CONFIG["archdir"]
archdir 目录中包含了特定架构的扩展和库文件,都是以 .bundle 结尾的 C 语言扩展文件,它们都是二进制文件,用户不可读但是 ruby 解释器可以读懂,只有在运行时可以加载。
Ruby 程序中使用这些由 C 语言编写的标准库的方式也是使用 require
关键字加载。
User 自定义的 Ruby 的扩展库 RbConfig::CONFIG["rubylibdir"] 和 User 安装的第三方的扩展库 Ruby 的标准库子目录 RbConfig::CONFIG["rubylibdir"]
site_ruby 和 vendor_ruby 目录中包含了是用于自定义的库或者是通过 gem 工具安装的第三方的库。
gems 目录
RubyGems 工具是打包和发布 Ruby 库文件的标准方式,相当于 Java 中的 Maven,用户可以使用 gem 工具来安装第三方的扩展。当用户安装 gems 时,未绑定的库文件会放置在 gems 目录中。
安装 Ruby 是一同安装的扩展通常成为 Ruby 的标准库,与 Python 的标准库一样,Ruby 的中的大量标准库也提供了非常多的功能或者扩展,包括数据库管理、网络、数据分析等。标准库精密的结构每次改变,都要随着 Ruby 新版本的发布而发布,而使用最多最广泛的库则已经趋于稳定。
使用标准库和第三方扩展的关键字是 require
,除此之外还可以使用 load
方法,这些方法可以在运行时加载标准库或者第三方扩展。
load
在编写大型的 Ruby 应用时,不可能将所有的代码放在一个文件中,我们需要将程序功能拆分,每个功能后者几个功能单独放在一个文件中,而加载或者引用这些单独文件中所编写的功能就需要使用到 require
和 load
。
首先来看 load
的使用,新建一个 buy.rb 文件,包含如下代码:
puts "罗老师说要一个中杯的拿铁"
load "coffee.rb"
puts "罗老师疯了...."
该代码中通过 load
方法加载了 coffee.rb 文件,在同级目录下创建 coffee.rb,代码如下:
puts "服务员:对不起先生,这个是大杯"
puts "服务员:这个才是中杯"
puts "服务员:中杯、大杯、特大杯"
执行 buy.rb,输出结果如下:
罗老师说要一个中杯的拿铁
服务员:对不起先生,这个是大杯
服务员:这个才是中杯
服务员:中杯、大杯、特大杯
罗老师疯了....
load
的使用非常简单,后面要跟具体的 Ruby 文件的名称,要加双引号且不能省略扩展名,ruby 解释器可以根据名称找到加载的文件,如果不在同级目录,ruby 解释器将在加载路径中找到。
ruby 解释器的加载路径是一些列目录的集合,ruby 将在这些目录中搜索指定的文件名,使用 load 加载文件时可以使用相对路径也可以使用绝对路径。
load
是一个方法,只要执行到 load
这行代码是才会加载指定的文件,出现几次 load
就加载几次,并且几次加载同一个文件时最新的文件将会覆盖之前加载的文件。
require
require
是一个关键字,load
是一个方法,load
在代码中可以多次执行相同的文件,而 require
不会加载已经加载过的文件。
修改 buy.rb,使用 require 关键字,修改后的代码如下:
puts "罗老师说要一个中杯的拿铁"
require "./coffee.rb"
puts "罗老师疯了...."
执行 buy.rb 文件,输出结果如下:
罗老师说要一个中杯的拿铁
服务员:对不起先生,这个是大杯
服务员:这个才是中杯
服务员:中杯、大杯、特大杯
罗老师疯了....
使用 require 时要选择相对路径,统计目录下直接使用文件名会报错:
puts "罗老师说要一个中杯的拿铁"
require "coffee.rb"
puts "罗老师疯了...."
执行 buy.rb 文件,控制台报错信息如下:
罗老师说要一个中杯的拿铁
Traceback (most recent call last):
2: from /ruby-tutorial/buy.rb:2:in `<main>'
1: from /Users/maverick/.rvm/rubies/ruby-2.7.6/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:83:in `require'
/Users/maverick/.rvm/rubies/ruby-2.7.6/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:83:in `require': cannot load such file -- coffee.rb (LoadError)
require
关键字加载用户自定义的 Ruby 文件是不能辨识出当前的工作目录,一定要显示的指定路径。
require
用于请求 Ruby 的标准库和第三方库,此时不需要指定标准库或者第三方库的路径。
require_relative
require_relative
会搜索相对于当前文件所在的目录来加载,修改 buy.rb 文件为如下内容:
puts "罗老师说要一个中杯的拿铁"
require_relative "coffee.rb"
puts "罗老师疯了...."
执行 buy.rb 代码,输出结果与之前内容保持一致。