我正在查看Ransack红宝石宝石的内容。基本上,它调用一个名为require_constants
的方法。而且该方法本身需要一个文件:
# ransack.rb
require 'ransack/adapters'
Ransack::Adapters.object_mapper.require_constants
# adapters.rb
module Ransack
module Adapters
def self.object_mapper
@object_mapper ||= instantiate_object_mapper
end
def self.instantiate_object_mapper
if defined?(::ActiveRecord::Base)
ActiveRecordAdapter.new
elsif defined?(::Mongoid)
MongoidAdapter.new
end
end
class ActiveRecordAdapter
def require_constants
require 'ransack/adapters/active_record/ransack/constants'
end
...
# constants.rb
module Ransack
module Constants
我相信第一个require
复制了ransack.rb中的adapters.rb的内容。因此,我们可以在没有未定义错误的情况下引用Ransack::Adapters
。
但是,当我们致电require_constants
时,它似乎会将Ransack::Constants
的内容复制到require_constants
的方法定义中。
require
那样做?其次,我知道模块不是局部变量,但在我尝试时,我甚至无法在控制台中定义模块:
class A
def a
module B end
end
end
SyntaxError: (irb):14: module definition in method body
那么require
做什么不会导致语法错误?
答案 0 :(得分:4)
"复印"这里说错了。 require
不会复制任何内容。它读取给定文件中的源代码,并在Ruby的全局(" main
")上下文中执行该代码(除非文件已经require
d;然后它什么也不做,返回false
)。引用the docs(强调我的):
加载的源文件中的任何常量或全局变量将在调用程序的全局命名空间中可用。
require
在方法调用内部或模块内部或其他任何位置的行为不同于文件顶部的行为。
当您在方法调用中看到require
时,原因通常是模块仅在特定场景中需要,并且在该场景发生之前加载它将是浪费的(因为,例如,模块需要在加载期间加载或访问的时间很长,只有在该场景中可用的资源 - 考虑不同的数据库驱动程序或操作系统。这并不意味着模块正在被加载到"方法或周围的代码,因为它不是require
所做的。
为了演示,假设我们有一个这样的模块:
# baby_module.rb
module BabyModule
NAME = "Baby"
end
假设我们运行以下程序:
module TheCorner
def self.load_baby_module
require File.expand_path("baby_module", __dir__)
end
end
TheCorner.load_baby_module
if defined?(TheCorner::BabyModule)
puts "#{TheCorner::BabyModule::NAME} is in TheCorner"
elsif defined?(BabyModule)
puts "Nobody puts #{BabyModule::NAME} in TheCorner"
end
正如您可能已经猜到的,该程序的输出将是:
没人把宝贝放在TheCorner中
答案 1 :(得分:0)
那么
@import 'file-that-has-been-removed-but-still-referenced';
做什么不会导致语法错误?
简单:它运行文件。