【问题标题】:Finding a gem from the require line in code从代码中的 require 行中查找 gem
【发布时间】:2011-09-23 17:54:14
【问题描述】:

我目前有一个安装程序,它可以安装一组 ruby​​ 脚本(即从主程序中进行的可选安装)。我编写了一个脚本,在安装后,它会扫描包含的 ruby​​ 文件中的所有 require 语句,然后提取所有“必需”文件。例如,它会寻找

require 'curb'
require 'rest-client'
# require etc...

这是在每个文件中,然后将它们包含在一个列表中(删除重复项),所以我有一个看起来像这样的数组:

"curb", "rest-client", etc...

对于大多数宝石来说,它非常好,因为名称匹配,我只是做一个

gem install GEMNAME

但是,如果名称不匹配,我正在尝试通过查询 gem 服务器找出一种从 require 行中找出 gem 名称的方法。例如:

xml-simple 有 xmlsimple 的 require 语句,但 gem 是 xml-simple。经过大量搜索,我能找到的唯一“解决方案”是安装每个 gem 并检查文件是否包含在

gem specification GEMNAME

这远非最佳,实际上是一个非常糟糕的主意,我想知道是否有一种方法可以查询 ruby​​gems 以查看 gem 中包含哪些文件。

【问题讨论】:

    标签: ruby rubygems


    【解决方案1】:

    Rubygems 有一个带有搜索端点的API

    /api/v1/search.(json|xml|yaml)?query=[YOUR QUERY]
    

    搜索端点列在Gem Methods。我确信这个搜索可以用来做你想做的事,也许可以通过提供部分名称并使用正则表达式来过滤关闭匹配项。

    编辑: 看看Bundler gem 本身也可能有用,因为如果我没记错的话,他们有时会在你打错字时推荐 gem。

    更新:

    我会遵循这样的工作流程:

    尝试安装 gems 是否需要它们。

    如果出现错误,请选择 gemname 的几个部分,例如 gem_name_str[0..5]gem_name_str[0..4]gem_name_str[0..3]

    使用这些字符串查询 API。

    删除重复项

    使用动态生成的正则表达式测试返回的值。比如:

    #given @param name = string from 'require' statement
    
    values_returned_from_api.each do |value|
      split_name = name.split(//)
      split_value = value.split(//)
      high_mark = 0
    
      #this will find the index of the last character which is the same in both strings
      for (i in 0..split_name.length) do
        if split_name[i] == split_value[i]
          high_mark = i
        else
          break
        end
      end
    
      #this regex will tell you if the names differ by only one character
      #at the point where they stopped matching. In my experience, this has
      #been the only way gem names differ from their require statement.
      #such as 'active_record'/'activerecord', 'xml-simple'/'xmlsimple' etc...
    
      #get the shorter name of the two
      regex_str = split_name.length < split_value.length ? split_name : split_value
    
      #get the longer name of the two
      comparison_str = split_name.length < split_value.length ? value : name
    
      #build the regex
      regex_str.insert((high_mark + 1), '.')  #insert a dot where the two strings differ
      regex = /#{regex_str.join('')}/
    
      return name if comparison_str =~ regex
    end
    

    注意:此代码未经测试。它只是为了说明这一点。它也可能被优化和浓缩。

    我假设 API 返回部分匹配。我还没有真正尝试过。

    【讨论】:

    • 我从搜索 API 看到的唯一问题是您仍然必须提供 gem 名称。也无法通过该搜索查看 gemfile 中包含的内容。
    • 给定一个部分 gemname,你应该得到一个潜在匹配的列表。然后,您可以使用正则表达式扫描这些最有可能的候选人。有关更多信息,请参阅更新后的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    相关资源
    最近更新 更多