Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有可能';卸载&x27;(';不需要';)Ruby库?_Ruby_Nokogiri_Google Drive Api - Fatal编程技术网

有没有可能';卸载&x27;(';不需要';)Ruby库?

有没有可能';卸载&x27;(';不需要';)Ruby库?,ruby,nokogiri,google-drive-api,Ruby,Nokogiri,Google Drive Api,我希望加载一些库,让它们做一些工作,然后执行与require相反的操作,以避免以后出现兼容性错误。我不希望必须转储到文件并重新启动shell,因为创建的对象(如数据)可以被我的其他库很好地处理,而不是在我试图卸载的早期库存在的情况下 有人有什么建议或者知道这是否可行吗?除了“看起来Webrick设法做到了这一点”之外,没有得出什么明智的结论 有问题的库是(电子表格处理库Roo依赖于Google_drive进行在线电子表格读/写,如该链接所述)。我不知道任何卸载文件的方法,但您可以将手动选取的全局

我希望加载一些库,让它们做一些工作,然后执行与
require
相反的操作,以避免以后出现兼容性错误。我不希望必须转储到文件并重新启动shell,因为创建的对象(如
数据
)可以被我的其他库很好地处理,而不是在我试图卸载的早期库存在的情况下

有人有什么建议或者知道这是否可行吗?除了“看起来Webrick设法做到了这一点”之外,没有得出什么明智的结论


有问题的库是(电子表格处理库Roo依赖于Google_drive进行在线电子表格读/写,如该链接所述)。

我不知道任何卸载文件的方法,但您可以将手动选取的全局变量重置为零和取消定义常量(这足够接近):

根据冲突的内容,您还可以临时重命名冲突的类:

Bar = Foo
Object.send(:remove_const, :Foo)
do_stuff
Foo = Bar

不幸的是,Ruby的两个特性在您希望干净地“卸载”一个库时已经结束。首先,“加载”Ruby库可以运行任意Ruby代码。其次,可以在Ruby中动态地重新定义现有的常量和方法

如果Ruby库只定义了新的类和模块,那么可以像@Denis指出的那样简单地取消定义它们。然而,在这种情况下,“兼容性错误”是不太可能发生的,即使您只是让它们保持原样。如果一个库猴子修补核心Ruby类,创建信号处理程序,或者在退出时设置跟踪挂钩或
挂钩,那么将非常非常很难追踪所有已更改的内容,并彻底逆转更改

最好的方法是首先加载数据,然后使用类似于
Process 35; fork
的方法来生成一个新的shell,然后加载库。完成后,杀死子shell并返回父shell。您的数据仍将存在


并使用类似的技术避免重复等待Rails加载。也许你可以修改他们的一些作品。

就像@Alex所说的,你可以使用创建一个新的ruby进程,在那里你将
需要
你的库。新的分叉进程将有权访问父进程中加载的数据:

def talk(msg)
  # this will allow us to see which process is
  # talking
  puts "#{Process.pid}: #{msg}"
end

# this data was loaded on the parent process
# and will be use in the child (and in the parent)
this_is_data = ["a", "b", "c"]

talk "I'm the father process, and I see #{this_is_data}"

# this will create a new ruby process
fork{
  talk "I'm another process, and I also see #{this_is_data}"
  talk "But when I change `this_is_data`, a new copy of it is created"
  this_is_data << "d"
  talk "My own #{this_is_data}"
}

# let's wait and give a chance to the child process
# finishes before the parent
sleep 3

talk "Now, in the father again, data is: #{this_is_data}"
这很好!由
fork
创建的每个进程都是一个O.S.级别的进程,并在自己的内存空间中运行

要以某种方式管理通过加载文件创建的全局变量,可以做的另一件事是将
require
的使用替换为
load
。这种方法并不能解决已经指出的所有问题,但确实有帮助。请参见以下规格:

require "minitest/autorun"

describe "Loading files inside a scope" do

  def create_lib_file(version)
    libfile = <<CODE
      class MyLibrary#{version}
        VERSION = "0.0.#{version}"
      end

      class String
        def omg_danger!
        end
      end

      puts "loaded \#{MyLibrary#{version}::VERSION}"
    CODE

    File.write("my_library.rb", libfile)
  end

  after do
    File.delete("my_library.rb") if File.exists?("my_library.rb")
  end

  describe "loading with require" do
    it "sees the MyLibrary definition" do
      create_lib_file("1")
      require_relative "my_library.rb"
      MyLibrary1::VERSION.must_be :==, "0.0.1"
      "".respond_to?(:omg_danger!).must_be :==, true
    end
  end

  describe "loading with #load " do
    describe "without wrapping" do
      it "sees the MyLibrary definition" do
        create_lib_file("2")
        load "my_library.rb"
        MyLibrary2::VERSION.must_be :==, "0.0.2"
        "".respond_to?(:omg_danger!).must_be :==, true
      end
    end

    describe "using anonymous module wraping" do
      it "doesn't sees MyLibrary definition" do
        create_lib_file("3")
        load "my_library.rb", true
        ->{ MyLibrary3 }.must_raise NameError
        "".respond_to?(:omg_danger!).must_be :==, false
      end
    end
  end
end

不管通常怎么说,使用此过程可以取消请求/卸载包

  • 假设所需文件存储为
    d:/foo.rb
    ,包含以下简单内容:
  • 在Ruby中,任何类、模块或方法都被定义为常量,因此您可以首先取消链接:
  • 已经需要/加载的文件记录在全局变量
    $“
    中,然后需要从中清除已经需要的文件:
  • 现在您可以再次请求文件,所有内容都将刷新并可用
  • irb(main):008:0>需要'd:/foo.rb'
    =>正确
    irb(main):009:0>$”。选择{r | r.include?'foo.rb}
    =>[“d:/foo.rb”]
    irb(主要):010:0>定义?福
    =>“常数”
    irb(主):011:0>Foo.new
    => #
    
    这一点很好。不幸的是,这不会逆转应用于核心Ruby类的monkey补丁,等等。这看起来很棘手,我无法在程序中完成。。。看起来我必须找到一个解决方法,所以如果我初始化
    数据
    ,然后
    处理#fork
    ,新shell是否已经初始化了
    数据
    ?另外,如果我在子shell中使用
    data
    并生成
    newdata
    ,那么当我杀死子shell时,父shell中仍然可以使用
    newdata
    ?嗯,Windows不支持
    fork
    ---另一种选择,
    process.spawn
    ()据称在Windows(Ruby 1.9.x)上工作,但是:-(看起来我将再次为我的Chromebook植根lol1.是的。2.否。(当你采用新流程时,它是旧流程的“复写本”。但在新流程中所做的任何更改都不会对旧流程产生影响。)
    23520: I'm the father process, and I see ["a", "b", "c"]
    23551: I'm another process, and I also see ["a", "b", "c"]
    23551: But when I change `this_is_data`, a new copy of it is created
    23551: My own ["a", "b", "c", "d"]
    23520: Now, in the father again, data is: ["a", "b", "c"]
    
    require "minitest/autorun"
    
    describe "Loading files inside a scope" do
    
      def create_lib_file(version)
        libfile = <<CODE
          class MyLibrary#{version}
            VERSION = "0.0.#{version}"
          end
    
          class String
            def omg_danger!
            end
          end
    
          puts "loaded \#{MyLibrary#{version}::VERSION}"
        CODE
    
        File.write("my_library.rb", libfile)
      end
    
      after do
        File.delete("my_library.rb") if File.exists?("my_library.rb")
      end
    
      describe "loading with require" do
        it "sees the MyLibrary definition" do
          create_lib_file("1")
          require_relative "my_library.rb"
          MyLibrary1::VERSION.must_be :==, "0.0.1"
          "".respond_to?(:omg_danger!).must_be :==, true
        end
      end
    
      describe "loading with #load " do
        describe "without wrapping" do
          it "sees the MyLibrary definition" do
            create_lib_file("2")
            load "my_library.rb"
            MyLibrary2::VERSION.must_be :==, "0.0.2"
            "".respond_to?(:omg_danger!).must_be :==, true
          end
        end
    
        describe "using anonymous module wraping" do
          it "doesn't sees MyLibrary definition" do
            create_lib_file("3")
            load "my_library.rb", true
            ->{ MyLibrary3 }.must_raise NameError
            "".respond_to?(:omg_danger!).must_be :==, false
          end
        end
      end
    end
    
    Run options: --seed 16453
    
    # Running tests:
    
    loaded 0.0.3
    .loaded 0.0.2
    .loaded 0.0.1
    .
    
    Finished tests in 0.004707s, 637.3486 tests/s, 1274.6973 assertions/s.
    
    3 tests, 6 assertions, 0 failures, 0 errors, 0 skips
    
    class Foo
    
    end
    
    irb(main):001:0> require 'd:/foo.rb'
    => true
    irb(main):002:0> defined? Foo
    => "constant"
    irb(main):003:0> Object.send(:remove_const, :Foo)
    => Foo
    irb(main):004:0> defined? Foo
    => nil
    
    irb(main):005:0> $".select{|r| r.include? 'foo.rb'}
    => ["d:/foo.rb"]
    irb(main):006:0> $".delete('d:/foo.rb')
    => "d:/foo.rb"
    irb(main):007:0> $".select{|r| r.include? 'foo.rb'}
    => []
    
    irb(main):008:0> require 'd:/foo.rb'
    => true
    irb(main):009:0> $".select{|r| r.include? 'foo.rb'}
    => ["d:/foo.rb"]
    irb(main):010:0> defined? Foo
    => "constant"
    irb(main):011:0> Foo.new
    => #<Foo:0x000000033ff8d8>