我可以有条件地跳过加载吗;“进一步”;同一文件中的ruby代码?

我可以有条件地跳过加载吗;“进一步”;同一文件中的ruby代码?,ruby,rubygems,require,Ruby,Rubygems,Require,我是否可以有条件地跳过在同一文件中加载“进一步”ruby代码, 如果找不到库(通过require加载) 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 "==

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

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在以后不要再加载文件吗 击中
救援装载错误

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

需要它,因为我有一个rake任务,它需要
awsdk
rubygem,但我只使用它 在我的本地机器上。如果未找到
aws sdk
,则以后在同一文件中加载代码是没有意义的。我想我可以将代码拆分成更小的文件,并将其扭曲 紧急电话

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
后继续执行程序。即:优雅地处理
LoadError
,不要将
LoadError
之后编写的代码加载到同一文件中。无法在
LoadError
上引发
exit
abort
,尤其是
LoadError
之后的代码不应由ruby解释器执行(或加载)

原来问过
但我没有正确地提出这个问题。希望这是更好的措辞

我还没有检查源代码,但我想,当您在控制台上运行
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>'
在original.rb中,将
throw:aws_sdk
替换为
return

$ ruby -w treq2.rb 
in original, not to be modified
aws-sdk gem not found
rescued LocalJumpError
... continued
这样就行了。
HTH

是“顶级返回”功能


现在可以在顶层使用
return
关键字,如“通过一个if条件”示例

不需要“跳过”文件的其余部分,因为它已经“加载”了。如果出现
rescue LoadError
,代码将终止(使用
return
或最好是
exit
),Ruby将不处理文件的其余部分。@BernardK谢谢。编辑了这个问题。希望它等同于将其包装在问题中提出的begin rescue或if块中。相关部分如下所示。希望在引发
LoadError
后继续执行程序。即:优雅地处理
LoadError
,不要将
LoadError
之后编写的代码加载到同一文件中。无法在
LoadError
上引发
exit
abort
,尤其是
LoadError
之后的代码不应由ruby解释器执行(或加载)。此文件是如何加载的?我不知道。它需要你的文件吗?我想Ruby 2正在考虑这个问题。我不知道是否有任何实现已经进入Ruby 2预览版。的可能副本不理解第二个示例,即使用
LocalJumpError
。在第一个示例中,我没有得到任何错误。我使用的是ruby 1.9.3p327您使用的是两个单独的文件吗?错误只发生在两个文件中。是的。实际代码(从示例中复制)和输出位于。我使用的是MRI ruby 1.9.3p327(2012-11-10版本37606)[x86_64-darwin10.8.0]ruby安装没有任何自定义补丁我已经安装了ruby-1.9.3-p362。现在,将catch/throw分发到两个文件中的版本以及return/rescue版本都可以正常工作。你现在快乐吗?这就是你想要的吗?@deepak回答你的第一个评论:如果你运行
ruby original.rb
,返回
而不是
throw
,“rescue in”中的错误
:意外返回(LocalJumpError)
,但是如果需要从另一个文件运行original.rb,我们可以捕获错误,解救它并继续。
$ ruby -w treq2.rb 
in original, not to be modified
aws-sdk gem not found
rescued LocalJumpError
... continued