gpt4 book ai didi

ruby - 无论如何要在 REPL 中重新加载修改后的 gem 文件

转载 作者:数据小太阳 更新时间:2023-10-29 07:08:10 25 4
gpt4 key购买 nike

在尝试构建 Ruby gem(使用 Bundler)时,我倾向于使用 Bundler 提供的 REPL 测试代码——可通过 bundle console 访问。

有什么方法可以重新加载整个项目吗?我最终再次加载单个(更改的)文件以测试新更改。

最佳答案

以下 hack 适用于我的一个相对简单的 gem 和 Ruby 2.2.2。我很想看看它是否适合你。它做出以下假设:

  1. 您具有传统的文件夹结构:一个名为 lib/my_gem_name.rb 的文件和一个文件夹 lib/my_gem_name/,其中包含任何文件/文件夹结构。
  2. 您要重新加载的所有类都嵌套在您的顶级模块 MyGemName 中。

如果在 lib/my_gem_name/ 下的其中一个文件中,您在 MyGemName 命名空间之外的猴子补丁类中,它可能无法工作。

如果您对上述假设很满意,请将以下代码放入 lib/my_gem_name.rb 中的模块定义中并试一试:

module MyGemName

def self.reload!
Reloader.new(self).reload
end

class Reloader
def initialize(top)
@top = top
end

def reload
cleanup
load_all
end

private

# @return [Array<String>] array of all files that were loaded to memory
# under the lib/my_gem_name folder.
# This code makes assumption #1 above.
def loaded_files
$LOADED_FEATURES.select{|x| x.starts_with?(__FILE__.chomp('.rb'))}
end

# @return [Array<Module>] Recursively find all modules and classes
# under the MyGemName namespace.
# This code makes assumption number #2 above.
def all_project_objects(current = @top)
return [] unless current.is_a?(Module) and current.to_s.split('::').first == @top.to_s
[current] + current.constants.flat_map{|x| all_project_objects(current.const_get(x))}
end

# @return [Hash] of the format {Module => true} containing all modules
# and classes under the MyGemName namespace
def all_project_objects_lookup
@_all_project_objects_lookup ||= Hash[all_project_objects.map{|x| [x, true]}]
end

# Recursively removes all constant entries of modules and classes under
# the MyGemName namespace
def cleanup(parent = Object, current = @top)
return unless all_project_objects_lookup[current]
current.constants.each {|const| cleanup current, current.const_get(const)}
parent.send(:remove_const, current.to_s.split('::').last.to_sym)
end

# Re-load all files that were previously reloaded
def load_all
loaded_files.each{|x| load x}
true
end
end
end

如果您不希望此功能在生产中可用,请考虑在 bin/console 脚本中对其进行猴子修补,但请确保更改行 $LOADED_FEATURES.select {|x| x.starts_with?(__FILE__.chomp('.rb'))} 到将在给定代码新位置的情况下返回相关加载文件列表的内容。

如果你有一个标准的 gem 结构,这应该有效:$LOADED_FEATURES.select{|x| x.starts_with?(File.expand_path('../../lib/my_gem_name'))}(确保在 IRB.startPry.start)

关于ruby - 无论如何要在 REPL 中重新加载修改后的 gem 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22732263/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com