On Sun, May 23, 2010 at 1:21 AM, Chad Woolley <thewoolley...@gmail.com> wrote: > 1. Are we doing it wrong? Does the RubyGems API provide a way to avoid > this manual parsing? > 2. Should there be a --[no-]platforms option to the 'list' command, > which would have made these updates to the parsing logic unnecessary?
So, I found Eric Hodel's admonishment "Why aren't you using the RubyGems API?" [1], but that's easier said than done. James Tucker followed with this example [2], but that doesn't help, because it isn't a remote call (just gives an array of "name-version" local entries). The only thing the API provides now is Gem.source_index for local gems, and Gem::SpecFetcher.fetcher for remote gems. Both of these return giant nested hashes and arrays of various nested values and objects. That's not too user-friendly or intuitive, which is why I think people just end up parsing the output of gem list. For example, here's the API call to see if a gem with the specified name_to_find, version_to_find, and platform_to_find exists remotely: name_to_find=/^json$/; version_to_find = '1.4.3'; platform_to_find='x86-mingw32'; Gem::SpecFetcher.fetcher.find_matching(Gem::Dependency.new(name_to_find,version_to_find),false,false).map{|spec_tuple| spec = spec_tuple.first; spec[2] == platform_to_find }.any?{|found| found == true} Is there something simpler? Maybe. I'm not sure. Like I said, not very intuitive, and looking at the RubyGems code for examples doesn't help much (e.g. the 225-line query_command#output_query_results) What are the problems? One problem is the lack of objects here. Returning a giant nested hash or array isn't a humane API. A second problem is the coupling of the version and platform concepts. Ideally, I'd like to have these abstractions: * A Gem has one or more Versions. * Each Version has one or more Platforms. Instead, SpecFetcher provides this representation of the platforms supported by a specific gem name and version: Gem::SpecFetcher.fetcher.find_matching(Gem::Dependency.new(/^json$/,'1.4.3'),true,false) [[["json", #<Gem::Version "1.4.3">, "x86-mingw32"], "http://rubygems.org/"], [["json", #<Gem::Version "1.4.3">, "ruby"], "http://rubygems.org/"], [["json", #<Gem::Version "1.4.3">, "x86-mswin32"], "http://rubygems.org/"]] What can we do? When I think of an "easy" API for this, it's kind of hard given these issues. Maybe we could at least provide something for the common use case chef and geminstaller had, which is "does this gem name (and optionally version/platform) exist remotely?" exists_remotely?(name, version=nil, platform=nil) where version and and platform would be defaulted to match anything. This method could be anywhere, on Gem, or a FriendlyApi module mixed into Gem; whatever as it is intuitive and easily found. Anyway, just some thoughts, because it's not cool to tell people "Use the API!" when that is only possible given a fairly deep understanding of RubyGems internals... -- Chad [1] https://tickets.opscode.com/browse/CHEF-1168?focusedCommentId=13981&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_13981 [2] https://tickets.opscode.com/browse/CHEF-1168?focusedCommentId=13983&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_13983 _______________________________________________ Rubygems-developers mailing list http://rubyforge.org/projects/rubygems Rubygems-developers@rubyforge.org http://rubyforge.org/mailman/listinfo/rubygems-developers