我们的团队正在开发一个新的应用程序,我们从Rails 3.1和Ruby 1.9.2开始 - 昨晚我把它带到了Ruby 1.9.3。
我们在依赖链中使用的一个宝石(css_parser)最终在其中有一个require'iconv',在1.9.3中触发a deprecation warning看起来像这样:
.../gems/activesupport-3.1.1/lib/active_support/dependencies.rb:240:in `block in require': iconv will be deprecated in the future, use String#encode instead.
起初我天真地指责铁轨没有更好的痕迹,直到我没有在任何地方找到需要'iconv'。
我追踪这个问题的唯一方法就是我开始在我的Gemfile中评论事情,然后我终于有了明智的想法来加载irb并开始依次要求每个库。我也可以在gems目录中完成一个文件系统grep,但我不确定“require'iconv'”是触发错误的原因。
什么是PITA。必须有一个更好的方法 - 只是在rake任务中执行--trace,加载rails没有削减它。是否有某种方式/任何方式触发跟踪,这将显示相对较长的库依赖项列表中的哪一行触发了弃用?
答案 0 :(得分:6)
所以,它可能有点没有实际意义,因为我不太可能再遇到这个问题(并且css_parser gem是我当前Rails 3.1 / Ruby 1.9中唯一需要iconv的宝石。 3个项目)。
但 是一个谜题,所以我想找到解决问题的方法。
在这种情况下,问题非常特定于iconv。还有其他ruby弃用,但在大多数情况下,它们似乎通过内核#warn(如果是ruby)或rb_warn()(如果是C) - 但warning in iconv.c is a little different而不是其他 - 无论如何它是' sa放到rb_stderr。
所以也许我可以做以下
事实证明我不能做#4 - 因为Bundler直接调用了Kernel.require - 但是我可以使用Bundler来解析Gemfile以给我一个需要自己的东西列表。
所以这就是我得到的 - 感谢this stack overflow post获取标准错误的指针 - 以及aliasing the original Kernel#require上的想法的rubygems来源
# override Kernel#require to intercept stderr messages on require
# and raise a custom error if we find one mentioning 'iconv'
require "stringio"
class RequireError < StandardError
end
module Kernel
alias :the_original_require require
private :the_original_require
def capture_stderr
# The output stream must be an IO-like object. In this case we capture it in
# an in-memory IO object so we can return the string value. You can assign any
# IO object here.
previous_stderr, $stderr = $stderr, StringIO.new
yield
$stderr.string
ensure
# Restore the previous value of stderr (typically equal to STDERR).
$stderr = previous_stderr
end
def require(name)
captured_output = capture_stderr do
the_original_require(name)
end
if(captured_output =~ %r{iconv})
raise RequireError, 'iconv requirement found'
end
end
end
require 'bundler'
# load the list of Bundler requirements from the Gemfile
required_libraries = Bundler.definition.dependencies.map(&:name)
# loop through and require each, ignoring all errors other than
# our custom error
required_libraries.each do |requirement|
begin
require(requirement)
rescue Exception => e
if(e.class == RequireError)
raise e
end
end
end
瞧!跟踪消息,有助于追踪iconv要求的位置。
最后,可能只是搜索&#34;要求&#39; iconv&#39;&#34;仍然是最好的(一旦明确了导致错误的原因)。
但是,就像在生活中一样。 Some Yaks Must Be Shaved.
答案 1 :(得分:0)
您可以查看Gemfile.lock
文件,该文件包含分层树中的所有依赖项,并指示每个gem所需的版本。这可能有助于识别需要它的宝石。