Ruby空白环境的执行范围

时间:2012-07-19 15:34:09

标签: ruby scope require execution

我目前正在开发一个基本上执行另一个应用程序的框架,例如在另一个ruby程序的上下文中的rails。我最初的尝试只是像这样启动应用程序:

def load_app!

  # Load the rails application
  require './config/application'

  # Initialize the rails application
  @app = App::Application.initialize!

end

问题在于,框架是否需要与加载的应用程序发生冲突,因此initialize!调用永远不会起作用,尽管它会在普通的ruby程序中。

所以我的问题是,如果有人知道一种方法,基本上将此调用范围扩展为一个行为类似于空白RVM环境的单元。所以基本上是这样的行为:

require 'json'
puts JSON.generate({:name => "test"})

blank_environment do
  puts JSON.generate({:name => "test"})
  #=> uninitialized constant JSON

  require 'json'
  puts JSON.generate({:name => "test"})
end

没有取消定义或卸载当前加载的常量,因为我不知道所有这些因为我正在使用具有其他依赖性的gem。

那么有一种很酷的方式吗?或者其他任何方式来处理这个问题?

更新:

刚刚发现了一个想法。为什么ruby的require方法总是需要全局范围?将加载的模块实际范围放在当前模块下是不是一个非常好的功能?

module ScopeA
  require 'json' #> adds support for ScopeA::JSON  

  # due to normal ruby scoping everything can be called like normal in here
  JSON.parse("something")
end

# JSON should not be available here

module ScopeB
  require 'yaml'

  YAML.parse("something") # but no JSON, of course
end

这样的事情不存在吗? include已经必须知道常数......

提前致谢!

1 个答案:

答案 0 :(得分:0)

嗯,经过一些更多的研究,我似乎不可能按照我需要的方式进行研究。

我现在使用分布式ruby实现了一个基本版本,这对我不太满意:

require 'drb/drb'

URI = "druby://localhost:8787"

# Blank environment
pid = fork do
  Signal.trap("INT") { puts "Stopping Server.."; exit }

  class Application
    def call(env)
      [200,{},""]
    end
  end

  DRb.start_service(URI, Application.new)
  DRb.thread.join
end

# Working environment
DRb.start_service

app = DRbObject.new_with_uri(URI)
puts app.call({})

Process.kill("INT", pid)
Process.wait

如果有人想出更好的方法,我们非常感谢!