我在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却没有呢?
答案 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。