我可以有条件地跳过在同一个文件中加载“更多”红宝石代码吗?
Posted
技术标签:
【中文标题】我可以有条件地跳过在同一个文件中加载“更多”红宝石代码吗?【英文标题】:Can I conditionally skip loading "further" ruby code in the same file? 【发布时间】:2013-01-09 16:19:35 【问题描述】:我可以有条件地跳过在同一个文件中加载“更多”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 之后不要再加载文件了吗?
击中rescue LoadError
。
类似于提前返回,但用于加载文件而非函数。
需要它,因为我有一个需要 aws-sdk
rubygem 的 rake 任务,但我只使用它
在我的本地机器上。如果没有找到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
后继续执行程序。 IE。优雅地处理LoadError
并且不要在同一文件中加载LoadError
之后编写的代码。不能在 LoadError
上引发 exit
或 abort
尤其是 LoadError
之后的代码不应由 ruby 解释器执行(或加载)
本来问How to skip require in ruby? 但我没有正确地问这个问题。希望这个措辞更好
【问题讨论】:
没有必要“跳过”文件的其余部分,反正已经“加载”了。在rescue LoadError
的情况下,您的代码将终止(使用return
或最好使用exit
),Ruby 不会处理文件的其余部分。
@BernardK 谢谢。编辑了问题。希望它等同于将其包装在问题中所问的 begin-rescue 或 if-block 中。相关部分是。希望在引发LoadError
后继续执行程序。 IE。优雅地处理LoadError
并且不要在同一文件中加载LoadError
之后编写的代码。无法在 LoadError
上引发 exit
或 abort
尤其是 LoadError
之后的代码不应由 ruby 解释器执行(或加载)
这个文件是怎么加载的?我不认识瑞克。是require
你的文件吗?
我认为这正在考虑用于 Ruby 2:bugs.ruby-lang.org/issues/4840。不过,我不知道是否有任何实现进入 Ruby 2 预览版。
How to cancel evaluating a required Ruby file?的可能重复
【参考方案1】:
“***回归”功能has been added。
现在可以在顶层使用return
关键字,如您的“通过 if 条件”示例。 Further discussion here.
【讨论】:
【参考方案2】:我没有检查源代码,但我想,当您在控制台运行 ruby my_file.rb
或从 Ruby 代码运行 require/load
时,文件会在评估之前完全读入内存。恐怕没有跳过文件的一部分这样的事情。
我有一个关于接球/投球的想法。
需要文件(例如 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_sdk
替换为 return
:
$ ruby -w treq2.rb
in original, not to be modified
aws-sdk gem not found
rescued LocalJumpError
... continued
这样就可以了。 高温
【讨论】:
不理解第二个例子,即。使用LocalJumpError
。我在第一个示例中没有收到任何错误。我正在使用 ruby 1.9.3p327
您使用的是两个单独的文件吗?只有两个文件会出现错误。
实际上是的。实际代码(从您的示例中复制),输出位于gist.github.com/4644058。我正在使用 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 回答您的第一条评论:如果您使用return
运行ruby original.rb
,而不是throw
,错误in 'rescue in <main>': unexpected return (LocalJumpError)
,但如果另一个文件需要original.rb,我们可以捕获错误,挽救它并继续。以上是关于我可以有条件地跳过在同一个文件中加载“更多”红宝石代码吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何有条件地跳过 Grails Spring Security 插件过滤器链中的 SecurityContextPersistenceFilter 过滤器