Rails.application.config.autoload_paths和标准Ruby require / require_relative有什么区别?

时间:2018-08-20 19:58:41

标签: ruby-on-rails ruby require

我在application.rb中看到以下配置:

config.autoload_paths += %W(#{config.root}/app/models/custom_pack/base)
config.autoload_paths += Dir["#{config.root}/app/models/custom_pack/custom_container/**/"]
config.autoload_paths += Dir["#{config.root}/app/models/custom_pack/helpers/**/"]
config.autoload_paths += Dir["#{config.root}/app/models/custom_pack/extensions/**/"]

位于autoload_paths中:

Rails.application.config.autoload_paths.grep /custom/
 => ["/Users/dviglione/projects/core/app/models/custom_pack/base", "/Users/dviglione/projects/core/app/models/custom_pack/custom_container/", "/Users/dviglione/projects/core/app/models/custom_pack/helpers/", "/Users/dviglione/projects/core/app/models/custom_pack/extensions/"]

但是这些文件没有被加载。因为出现错误:

 `method_missing': undefined method `create_element' for #<MyElement:0x007f82eca39898> 

在应该加载的文件之一中定义了create_element方法。

但是,当我使用require / require_relative时,它确实起作用:

# /initializers/my_initializer.rb
require "custom_pack/base"

# models/custom_pack/base.rb    
require_relative 'custom_container/base'
require_relative 'custom_container/parent'
require_relative 'custom_container/child'

Dir[File.join(File.expand_path("../helpers", __FILE__), "*_helper.rb")].each { |file| require file }
Dir[File.join(File.expand_path("../extensions", __FILE__), "*_adapter.rb")].each { |file| require file }

根据我从文档中读取的内容,当您使用require'erb'时,Ruby在$ LOAD_PATH中列出的目录中查找文件。也就是说,Ruby遍历其所有目录,并针对每个目录检查它们是否具有名为“ erb.rb”的文件。如果找到它们中的任何一个,则解释器将其加载并结束搜索。否则,它将在列表的下一个目录中再次尝试。如果列表用尽,则会引发LoadError。对于自动加载,其想法是当诸如Post之类的常量被丢失时,例如在app / models中存在post.rb文件时,Rails将会找到它,对其进行评估,并将Post定义为副作用。 Rails有一个类似于$ LOAD_PATH的目录集合,可在其中查找post.rb。该集合称为autoload_paths。

那为什么需要require / require_relative起作用,而autoload_paths却没有呢?

1 个答案:

答案 0 :(得分:0)

这里可能发生了很多事情。

1。如果文件遵循以下路径:lib/foo/bar.rb,则该类需要按以下方式定义:

class Foo::Bar
end

2.Autoload还会延迟加载文件,这意味着仅在调用模型时才加载它们。 For example

puts "I was loaded!"

class MyLibrary
end

irb(main):001:0> require 'mylibrary'
I was loaded!
=> true

irb(main):001:0> autoload :MyLibrary, 'mylibrary'
=> nil
irb(main):002:0> MyLibrary.new
I was loaded!
=> #<MyLibrary:0x0b1jef>

对于autoload的实际用法,建议改用require。理论上,autoload听起来不错,但是当某些类依赖于其他模块时,它可能会引起问题。因此,autoload is in the process of being deprecated