5


如果找不到库(通过 require 加载),我可以有条件地跳过在同一文件中加载“更多”ruby 代码吗?

begin
  require 'aws-sdk'
rescue LoadError
  puts "aws-sdk gem not found"
  return #does not work. nor does next
end

# code after here should not be executed as `aws-sdk` gem was not found
puts "=== should not get executed"

namespace :db do
  desc "import local postgres database to heroku. user and database name is hardcoded"
  task :import_to_heroku => [:environment, "db:dump_for_heroku"] do
    # code using aws-sdk gem
  end
end

在上面的代码中,我可以要求 Ruby 在点击 rescue LoadError.

就像提前返回,但用于加载文件而不是函数。

需要它,因为我有一个需要aws-sdkruby​​gem 的 rake 任务,但我只在我的本地机器上使用它。如果aws-sdk没有找到,我以后在同一个文件中加载代码是没有意义的。我想我可以将代码拆分为较小的文件并在 require 调用中对其进行变形

if Rails.env.development?
  require 'import_to_heroku'
end

但不想扭曲或修改我现有的代码

此外,我可以将整个代码包装在一个条件中,但这并不优雅。begin-rescue 块也是一种显式控制流。我不想以任何方式包装或触摸原始代码

也许是一个 api,例如

require_or_skip_further_loading 'aws-ruby`

所以我希望我的代码在功能上等同于

begin
  require 'aws-sdk'

  namespace :db do
    desc "import local postgres database to heroku. user and database name is hardcoded"
    task :import_to_heroku => [:environment, "db:dump_for_heroku"] do
      # code using aws-sdk gem
    end
  end
rescue LoadError
  puts "aws-sdk gem not found"
end

或通过 if 条件

library_found = false
begin
  require 'aws-sdk'
  library_found = true
rescue LoadError
  puts "aws-sdk gem not found"
  return #does not work
end

if library_found      
  namespace :db do
    desc "import local postgres database to heroku. user and database name is hardcoded"
    task :import_to_heroku => [:environment, "db:dump_for_heroku"] do
    # code using aws-sdk gem
    end
  end
end

LoadError希望程序在引发后继续执行。IE。优雅地处理LoadError并且不加载LoadError在同一文件中编写的代码。cannot raise exitor abortonLoadError尤其是之后的代码LoadError不应由 ruby​​ 解释器执行(或加载)

最初问过如何在ruby中跳过require? 但我没有正确地问这个问题。希望这个措辞更好

4

2 回答 2

3

我没有检查源代码,但我想,当你ruby my_file.rb在控制台运行时,或者require/load从 Ruby 代码运行时,文件在被评估之前被完全读入内存。恐怕没有跳过文件的一部分这样的事情。

我有一个关于接球/投球的想法。

需要文件(例​​如 Rake 任务?) treq1.rb :

catch :aws_sdk do
    require_relative 'original'
end

puts '... continued'

您不想修改的原始文件 original.rb :

puts 'in original, not to be modified'
begin
  require 'aws-sdk'
rescue LoadError
  puts "aws-sdk gem not found"
  throw :aws_sdk
end

puts ">>> to execute only if 'aws-sdk' is found"

# namespace :db do ... etc
#end

执行 :

$ ruby -w treq1.rb 
in original, not to be modified
aws-sdk gem not found
treq1.rb:2:in `require_relative': method `backtrace' called on unexpected T_NODE object (0x007fd32b88e900 flags=0x381c klass=0x0) (NotImplementedError)
    from treq1.rb:2:in `block in <main>'
    from treq1.rb:1:in `catch'
    from treq1.rb:1:in `<main>'

谷歌搜索错误:http
://www.ruby-forum.com/topic/4406870 最近的帖子,没有答案。如果要包装代码,它可以在单个文件中工作。
让我们尝试另一种解决方案。假设您可以更改 Rake 任务 treq2.rb :

begin
    require_relative 'original'
rescue LocalJumpError
    puts 'rescued LocalJumpError'
end

puts '... continued'

在 original.rb 中,替换throw :aws_sdkreturn

$ ruby -w treq2.rb 
in original, not to be modified
aws-sdk gem not found
rescued LocalJumpError
... continued

这样就可以了。
高温高压

于 2013-01-25T21:00:42.630 回答
1

新增“顶级回归”功能。

现在可以return在顶层使用关键字,如您的“通过 if 条件”示例。在这里进一步讨论

于 2019-01-31T16:53:10.420 回答