ruby:如何在本地上下文中加载.rb文件。

时间:2022-09-04 08:06:25

How this simple task can be done in Ruby?
I have some simple config file

如何在Ruby中完成这个简单的任务?我有一些简单的配置文件

=== config.rb
config = { 'var' => 'val' }

I want to load config file from some method, defined in main.rb file so that the local variables from config.rb became local vars of that method.
Something like this:

我想从main中定义的某个方法加载配置文件。rb文件,使本地变量从配置。rb成为该方法的局部vars。是这样的:

=== main.rb
Class App
    def loader
        load('config.rb') # or smth like that
        p config['var']   # => "val"
    end
end

I know that i can use global vars in config.rb and then undefine them when done, but i hope there's a ruby way )

我知道我可以在config中使用全局vars。rb,然后在完成时取消它们的定义,但是我希望有一个ruby方法)

5 个解决方案

#1


1  

I do NOT recommend doing this except in a controlled environment.

除了在受控环境中,我不建议这样做。

Save a module to a file with a predetermined name that defines an initialize and run_it methods. For this example I used test.rb as the filename:

将模块保存到具有定义初始化和run_it方法的预定义名称的文件中。在这个例子中,我使用了test。rb文件名:

module Test
  @@classvar = 'Hello'
  def initialize
    @who = 'me'
  end

  def get_who
    @who
  end

  def run_it
    print "#{@@classvar} #{get_who()}"
  end
end

Then write a simple app to load and execute it:

然后编写一个简单的应用程序来加载和执行它:

require 'test'

class Foo
  include Test
end

END {
  Foo.new.run_it
}

# >> Hello me

Just because you can do something doesn't mean you should. I cannot think of a reason I'd do it in production and only show it here as a curiosity and proof-of-concept. Making this available to unknown people would be a good way to get your machine hacked because the code could do anything the owning account could do.

仅仅因为你能做某事并不意味着你应该做。我想不出我在生产中这么做的原因,只把它作为一种好奇和概念验证。让不知名的人可以使用它将是让您的机器被黑客攻击的好方法,因为代码可以做拥有帐户可以做的任何事情。

#2


11  

The config file.

配置文件。

{ 'var' => 'val' }

Loading the config file

加载配置文件

class App
  def loader
    config = eval(File.open(File.expand_path('~/config.rb')).read)
    p config['var']
  end
end

#3


6  

As others said, for configuration it's better to use YAML or JSON. To eval a file

正如其他人所说,对于配置,最好使用YAML或JSON。eval文件

binding.eval(File.open(File.expand_path('~/config.rb')).read, "config.rb") binding.eval(File.read(File.expand_path('~/config.rb')), "config.rb")

binding.eval(File.open(File.expand_path(~ / config.rb))。阅读,“config.rb”)binding.eval(以(File.expand_path(~ / config.rb)),“config.rb”)

This syntax would allow you to see filename in backtraces which is important. See api docs [1].

这种语法允许您在回溯中看到文件名,这一点很重要。查看api文档[1]。

Updated eval command to avoid FD (file descriptor) leaks. I must have been sleeping or maybe should have been sleeping at that time of the night instead of writing on *..

更新eval命令以避免FD(文件描述符)泄漏。我一定是在睡觉,或者可能应该在晚上的那个时候睡觉,而不是写在*上。

[1] http://www.ruby-doc.org/core-1.9.3/Binding.html

[1]http://www.ruby-doc.org/core-1.9.3/Binding.html

#4


5  

You certainly could hack out a solution using eval and File.read, but the fact this is hard should give you a signal that this is not a ruby-like way to solve the problem you have. Two alternative designs would be using yaml for your config api, or defining a simple dsl.

您当然可以使用eval和File破解一个解决方案。阅读,但这是很难的事实应该给你一个信号,这不是一种像红宝石一样的方法来解决你的问题。两种可选的设计是为配置api使用yaml,或者定义一个简单的dsl。

The YAML case is the easiest, you'd simply have something like this in main.rb:

YAML是最简单的,你只需要在main中有类似的东西。

Class App
  def loader
      config = YAML.load('config.yml')
      p config['var']   # => "val"
  end
end

and your config file would look like:

配置文件如下:

--- 
var: val

#5


1  

I just had to do a similar thing as I wanted to be able to load a "Ruby DLL" where it returns an anonymous class ( a factory for instances of things ) I created this which keeps track of items already loaded and allows the loaded file to return a value which can be anything - a totally anonymous Class, Module, data etc. It could be a module which you could then "include" in an object after it is loaded and it could could supply a host of "attributes" or methods. you could also add an "unload" item to clear it from the loaded hash and dereference any object it loaded.

我只需要做类似的事情,我想可以加载一个“Ruby DLL”,它返回一个匿名类(工厂实例的事情),我创建了这个跟踪项目已经加载,并允许加载文件返回值可以是任何东西——一个完全匿名类,模块、数据等等。它可能是一个模块,你可以“包括”对象加载后,它可以提供一个主机的属性或方法。您还可以添加一个“卸载”项,以从加载的散列中清除它,并取消对它加载的任何对象的引用。

module LoadableModule

@@loadedByFile_ = {};

def self.load(fileName)
    fileName = File.expand_path(fileName);
    mod = @@loadedByFile_[fileName];
    return mod if mod;
    begin           
        Thread.current[:loadReturn] = nil;
        Kernel.load(fileName);
        mod = Thread.current[:loadReturn];
        @@loadedByFile_[fileName] = mod if(mod);
    rescue => e
        puts(e);
        puts(e.backtrace);
        mod = nil;
    end
    Thread.current[:loadReturn] = nil;
    mod
end
def self.onLoaded(retVal)
    Thread.current[:loadReturn] = retVal;
end
end 

inside the loaded file:

在加载文件:

LoadableModule.onLoaded("a value to return from the loaded file");

#1


1  

I do NOT recommend doing this except in a controlled environment.

除了在受控环境中,我不建议这样做。

Save a module to a file with a predetermined name that defines an initialize and run_it methods. For this example I used test.rb as the filename:

将模块保存到具有定义初始化和run_it方法的预定义名称的文件中。在这个例子中,我使用了test。rb文件名:

module Test
  @@classvar = 'Hello'
  def initialize
    @who = 'me'
  end

  def get_who
    @who
  end

  def run_it
    print "#{@@classvar} #{get_who()}"
  end
end

Then write a simple app to load and execute it:

然后编写一个简单的应用程序来加载和执行它:

require 'test'

class Foo
  include Test
end

END {
  Foo.new.run_it
}

# >> Hello me

Just because you can do something doesn't mean you should. I cannot think of a reason I'd do it in production and only show it here as a curiosity and proof-of-concept. Making this available to unknown people would be a good way to get your machine hacked because the code could do anything the owning account could do.

仅仅因为你能做某事并不意味着你应该做。我想不出我在生产中这么做的原因,只把它作为一种好奇和概念验证。让不知名的人可以使用它将是让您的机器被黑客攻击的好方法,因为代码可以做拥有帐户可以做的任何事情。

#2


11  

The config file.

配置文件。

{ 'var' => 'val' }

Loading the config file

加载配置文件

class App
  def loader
    config = eval(File.open(File.expand_path('~/config.rb')).read)
    p config['var']
  end
end

#3


6  

As others said, for configuration it's better to use YAML or JSON. To eval a file

正如其他人所说,对于配置,最好使用YAML或JSON。eval文件

binding.eval(File.open(File.expand_path('~/config.rb')).read, "config.rb") binding.eval(File.read(File.expand_path('~/config.rb')), "config.rb")

binding.eval(File.open(File.expand_path(~ / config.rb))。阅读,“config.rb”)binding.eval(以(File.expand_path(~ / config.rb)),“config.rb”)

This syntax would allow you to see filename in backtraces which is important. See api docs [1].

这种语法允许您在回溯中看到文件名,这一点很重要。查看api文档[1]。

Updated eval command to avoid FD (file descriptor) leaks. I must have been sleeping or maybe should have been sleeping at that time of the night instead of writing on *..

更新eval命令以避免FD(文件描述符)泄漏。我一定是在睡觉,或者可能应该在晚上的那个时候睡觉,而不是写在*上。

[1] http://www.ruby-doc.org/core-1.9.3/Binding.html

[1]http://www.ruby-doc.org/core-1.9.3/Binding.html

#4


5  

You certainly could hack out a solution using eval and File.read, but the fact this is hard should give you a signal that this is not a ruby-like way to solve the problem you have. Two alternative designs would be using yaml for your config api, or defining a simple dsl.

您当然可以使用eval和File破解一个解决方案。阅读,但这是很难的事实应该给你一个信号,这不是一种像红宝石一样的方法来解决你的问题。两种可选的设计是为配置api使用yaml,或者定义一个简单的dsl。

The YAML case is the easiest, you'd simply have something like this in main.rb:

YAML是最简单的,你只需要在main中有类似的东西。

Class App
  def loader
      config = YAML.load('config.yml')
      p config['var']   # => "val"
  end
end

and your config file would look like:

配置文件如下:

--- 
var: val

#5


1  

I just had to do a similar thing as I wanted to be able to load a "Ruby DLL" where it returns an anonymous class ( a factory for instances of things ) I created this which keeps track of items already loaded and allows the loaded file to return a value which can be anything - a totally anonymous Class, Module, data etc. It could be a module which you could then "include" in an object after it is loaded and it could could supply a host of "attributes" or methods. you could also add an "unload" item to clear it from the loaded hash and dereference any object it loaded.

我只需要做类似的事情,我想可以加载一个“Ruby DLL”,它返回一个匿名类(工厂实例的事情),我创建了这个跟踪项目已经加载,并允许加载文件返回值可以是任何东西——一个完全匿名类,模块、数据等等。它可能是一个模块,你可以“包括”对象加载后,它可以提供一个主机的属性或方法。您还可以添加一个“卸载”项,以从加载的散列中清除它,并取消对它加载的任何对象的引用。

module LoadableModule

@@loadedByFile_ = {};

def self.load(fileName)
    fileName = File.expand_path(fileName);
    mod = @@loadedByFile_[fileName];
    return mod if mod;
    begin           
        Thread.current[:loadReturn] = nil;
        Kernel.load(fileName);
        mod = Thread.current[:loadReturn];
        @@loadedByFile_[fileName] = mod if(mod);
    rescue => e
        puts(e);
        puts(e.backtrace);
        mod = nil;
    end
    Thread.current[:loadReturn] = nil;
    mod
end
def self.onLoaded(retVal)
    Thread.current[:loadReturn] = retVal;
end
end 

inside the loaded file:

在加载文件:

LoadableModule.onLoaded("a value to return from the loaded file");