我的ruby文件中没有require 'date'语句,但我可以调用DateTime.now

dw1jzc5e  于 2023-01-16  发布在  Ruby
关注(0)|答案(1)|浏览(117)

我试图理解在ruby中导入文件是如何工作的,但是我几乎花了一整天的时间来弄明白为什么我可以在我的类中调用DateTime.now,而我没有调用require 'date。这些都是在docker容器示例上运行的,在那里我得到了ruby 3. 0. 3,让我卡住的是,当我试图在一个新的docker容器示例ruby 3. 0. 3上创建一个新的ruby文件时。尝试调用DateTime.now,但它不起作用。
我试着在项目中查找包含date一词的require语句,在该项目中我可以调用DateTime.now,但没有找到。
项目的gem文件,可以在其中调用DateTime而无需require语句

gem 'aws-sdk-s3', '~> 1.93'
gem 'mime-types'
gem 'optparse', '~> 0.1.0'

group :development do
  gem 'rubocop', '~> 1.12'
end

group :test do
  gem 'rspec', '~> 3.10'
  gem 'rubocop-rspec', '~> 2.2'
  gem 'webmock', '~> 3.12'
end

新项目的gem文件,在该文件中,如果没有require语句,我就无法调用DateTime

gem 'mime-types'
gem 'optparse', '~> 0.1.0'
gem 'gqli'

group :development do
  gem 'rubocop', '~> 1.12'
end

group :test do
  gem 'rspec', '~> 3.10'
  gem 'rubocop-rspec', '~> 2.2'
  gem 'webmock', '~> 3.12'
  gem 'test-unit', '~> 3.0'
end

唯一的区别是两个项目中的aws和gqli,但我尝试让它们都有相同的gem文件,它仍然不工作。

gab6jxml

gab6jxml1#

当您requireaws-sdk-s3 library(它是aws-sdk-s3 Gem库的一部分)时,require又是aws-sdk-core库:

# frozen_string_literal: true

# WARNING ABOUT GENERATED CODE
#
# This file is generated. See the contributing guide for more information:
# https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
#
# WARNING ABOUT GENERATED CODE

require 'aws-sdk-kms'
require 'aws-sigv4'
require 'aws-sdk-core'
#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

aws-sdk-core libraryaws-sdk-core Gem的一部分,它又使用Kernel#require_relative加载param_converter library,如下所示:

# client modules

require_relative 'aws-sdk-core/client_stubs'
require_relative 'aws-sdk-core/async_client_stubs'
require_relative 'aws-sdk-core/eager_loader'
require_relative 'aws-sdk-core/errors'
require_relative 'aws-sdk-core/pageable_response'
require_relative 'aws-sdk-core/pager'
require_relative 'aws-sdk-core/param_converter'
#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

然后,param_converter库依次加载date库:

# frozen_string_literal: true

require 'stringio'
require 'date'
#↑↑↑↑↑↑↑↑↑↑↑↑↑

aws-sdk-core Gem不依赖于date Gem:

> spec.add_dependency('jmespath', '~> 1', '>= 1.6.1') # necessary for secure jmespath JSON parsing
> spec.add_dependency('aws-partitions', '~> 1', '>= 1.651.0') # necessary for new endpoint resolution
> spec.add_dependency('aws-sigv4', '~> 1.5') # necessary for making Aws::STS, SSO, SSOOIDC API calls
> spec.add_dependency('aws-eventstream', '~> 1', '>= 1.0.2') # necessary for binary eventstream

但是你不必依赖date Gem来使用date library,因为date Gem是default Gem,这意味着它是Ruby标准库的一部分,由Ruby开发人员维护,不需要安装,不需要列为Gem依赖项,也不需要激活。
这就是为什么您不必亲自对date库执行require操作的原因:因为require是一个库,而require又是另一个库,而require_relative又是另一个库,而require又是date库。
但更有趣的问题是,* 应该 * 使用require来运行date库吗?答案是,* 是的 *,您应该这样做。依赖这样的require链是非常脆弱的:如果在这条链中间的某个库决定改变它的内部结构,例如,使用不同的库来验证日期,或者自己实现日期验证,那么你的代码会无缘无故地中断。
我通常遵循的规则是 * 每个脚本必须独立 ,即每个脚本必须require其所有依赖项。
现在,在较大的应用程序中,这可能会变得很烦人,甚至可能会导致很长的启动延迟。一个很好的例子是框架或DSL,其中只是“期望”框架或DSL为您提供一组已经预加载的库。想象一下,您必须对每个active_support库、active_model库、active_relation库你在Ruby on Rails应用程序中使用的。这将是愚蠢的:如果您编写了Ruby on Rails模型,那么您 * 知道 * active_model已经加载,您不需要再次加载它。
所以,一个稍微宽松的规则是:
每个要成为require或由客户端执行的脚本必须独立 *。应用程序内部的脚本可能依赖于关于哪些库已经是required的内部知识。

相关问题