lib/lookup.rb in lookup-0.3.3 vs lib/lookup.rb in lookup-0.4.0
- old
+ new
@@ -1,58 +1,33 @@
require 'rubygems'
+require 'net/http'
+
require 'active_record'
+require 'nokogiri'
+require 'find_by_hash'
module APILookup
class << self
- def update
- require 'hpricot'
- require 'net/http'
+ def update!
puts "Updating API, this may take a minute or two. Please be patient!"
- Constant.delete_all
- Entry.delete_all
- # Ruby on Rails Classes & Methods
- update_api("Rails", "http://api.rubyonrails.org")
- # Ruby Classes & Methods
- update_api("Ruby", "http://www.ruby-doc.org/core")
+ [Constant, Entry, Api].map { |klass| klass.delete_all }
- weight_results
- puts "Updated API index! Use the lookup <method> or lookup <class> <method> to find what you're after"
+ update_api!("Rails", "http://api.rubyonrails.org")
+ update_api!("Ruby 1.8.7", "http://www.ruby-doc.org/core")
+ update_api!("Ruby 1.9", "http://ruby-doc.org/ruby-1.9")
+
end
-
- def update_api(name, url)
+
+ def update_api!(name, url)
puts "Updating API for #{name}..."
- Api.find_or_create_by_name_and_url(name, url)
- update_methods(Hpricot(Net::HTTP.get(URI.parse("#{url}/fr_method_index.html"))), url)
- update_classes(Hpricot(Net::HTTP.get(URI.parse("#{url}/fr_class_index.html"))), url)
+ api = Api.find_or_create_by_name_and_url(name, url)
+ api.update_methods!
+ api.update_classes!
puts "DONE (with #{name})!"
end
-
- def update_methods(doc, prefix)
- doc.search("a").each do |a|
- names = a.inner_html.split(" ")
- method = names[0]
- name = names[1].gsub(/[\(|\)]/, "")
- # The same constant can be defined twice in different APIs, be wary!
- url = prefix + "/classes/" + name.gsub("::", "/") + ".html"
- constant = Constant.find_or_create_by_name_and_url(name, url)
- constant.entries.create!(:name => method, :url => prefix + "/" + a["href"])
- end
- end
-
- def update_classes(doc, prefix)
- doc.search("a").each do |a|
- constant = Constant.find_or_create_by_name_and_url(a.inner_html, prefix + "/" + a["href"])
- end
- end
-
- # Weights the results so the ones more likely to be used by people come up first.
- def weight_results
- e = Constant.find_by_name("ActiveRecord::Associations::ClassMethods").entries.find_by_name("belongs_to")
- e.increment!(:weighting)
- end
-
+
def find_constant(name, entry=nil)
# Find by specific name.
constants = Constant.find_all_by_name(name, :include => "entries")
# search for class methods, which is prolly what we want if we can find it
constants = Constant.find_all_by_name("#{name}::ClassMethods", :include => "entries") if constants.empty?
@@ -67,11 +42,11 @@
if entry
constants = constants.select { |constant| !constant.entries.find_by_name(entry).nil? }
end
constants
end
-
+
# this uses a regex to lock down our SQL finds even more
# so that things like AR::Base will not match
# ActiveRecord::ConnectionAdapters::DatabaseStatements
def build_regex_from_constant(name)
parts=name.split("::").map do |c|
@@ -96,11 +71,11 @@
end
return ([rep] + parts[1..-1]).join("::")
end
name
end
-
+
# Find an entry.
# If the constant argument is passed, look it up within the scope of the constant.
def find_method(name, constant=nil)
methods = []
# Full match
@@ -120,28 +95,45 @@
methods = methods.select { |m| constants.include?(m.constant) }
end
methods
end
- def search(msg)
- msg = msg.split(" ")[0..-1].flatten.map { |a| a.split("#") }.flatten!
-
+ def search(msg, options={})
+ options[:api] ||= if /^1\.9/.match(msg)
+ "Ruby 1.9"
+ elsif /^1\.8/.match(msg)
+ "Ruby 1.8"
+ elsif /^Rails/i.match(msg)
+ "Rails"
+ end
+
+ msg = msg.gsub(/^(.*?)\s/, "") if options[:api]
+
+ splitter = options[:splitter] || "#"
+ parts = msg.split(" ")[0..-1].flatten.map { |a| a.split(splitter) }.flatten!
# It's a constant! Oh... and there's nothing else in the string!
- first = smart_rails_constant_substitutions(msg.first)
- if /^[A-Z]/.match(first) && msg.size == 1
- find_constant(first)
+ first = smart_rails_constant_substitutions(parts.first)
+ output = if /^[A-Z]/.match(first) && parts.size == 1
+ find_constant(first)
# It's a method!
else
# Right, so they only specified one argument. Therefore, we look everywhere.
- if msg.size == 1
- find_method(msg.last)
+ if parts.size == 1
+ o = find_method(parts.last)
# Left, so they specified two arguments. First is probably a constant, so let's find that!
else
- find_method(msg.last, first)
- end
+ o = find_method(parts.last, first)
+ end
+ o
end
+
+
+ output = search(msg, options.merge(:splitter => ".")) if output.empty? && splitter != "."
+
+ output = output.select { |m| m.api.name == options[:api] } if options[:api]
+ return output
end
-
+
end
end
require File.join(File.dirname(__FILE__), 'models')
\ No newline at end of file