ruby - 在方法中需要一个文件

标签 ruby

我正在查看 Ransack ruby 的内容。基本上,它调用一个名为 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 将 adapters.rb 的内容复制到 ransack.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 是怎么做到不会导致语法错误的呢?

最佳答案

“复制”在这里用错了。 require 不复制任何内容。它读取给定文件中的源代码并在 Ruby 的全局(“main”)上下文中执行该代码(除非该文件已经被 required;那么它什么都不做并返回 false)。引用the docs (强调我的):

Any constants or globals within the loaded source file will be available in the calling program’s global namespace.

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

正如您可能已经猜到的那样,该程序的输出将是:

Nobody puts Baby in TheCorner

关于ruby - 在方法中需要一个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39378109/

相关文章:

ruby - 在 ruby​​ 字符串中正确使用 gsub

ruby - 如何整理 ruby​​ 中格式错误的 xml

ruby-on-rails - 让 Rails 2.3.x 忽略 i18n gem

mysql - 将数据从 excel 文件写入数据库 (mysql) 时出现编码错误

javascript - 电子邮件正则表达式与 Ruby 和 Javascript 兼容

ruby-on-rails - Rails - 如何向 url 发出 GET 请求

ruby-on-rails - Rails simple_form gem 正在为预填充的输入添加绿色边框

Ruby Datamapper 通过 SSL 连接到 Amazon RDS 上的 MariaDB

ruby-on-rails - 使用 USR2 重新启动 Unicorn 似乎不会重新加载 production.rb 设置

ruby - Proc.new 绑定(bind)变化和循环逻辑抽象