我目前有一个安装程序,用于安装一组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
这远非最优,实际上是一个非常糟糕的主意,我想知道是否有办法查询rubygems以查看gem中包含的文件。
答案 0 :(得分:0)
Rubygems有API个搜索端点:
/api/v1/search.(json|xml|yaml)?query=[YOUR QUERY]
搜索端点列在Gem Methods。我确信这个搜索可以用来做你想要的,可能是通过提供部分名称和使用正则表达式来过滤关闭匹配。
编辑: 它也可能是看Bundler宝石本身的工作,因为如果我没记错的话,有时会推荐宝石。
更新
我会遵循这样的工作流程:
尝试安装宝石,只要它们是必需的。
如果出现错误,请选择宝石名称的几个部分,例如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返回部分匹配。我还没有尝试过。