Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Major update, see History: v0.2.0

  • Loading branch information...
commit a1d67d4cd491f1d54a6a3d0ba5a941d7e1c335c2 1 parent c595757
@marcandre marcandre authored
View
22 History.txt
@@ -1,6 +1,22 @@
-=== 1.0.0 / 2008-05-19
+=== 0.2.0 / 2009-11-17
-* 1 major enhancement
+* New features:
+ * results can use [] and []= for lookup and seting
+ * allows results to be open structs (default) or hash (by requiring 'googleajax/as_hash' instead)
- * Birthday!
+* bug fixes:
+ * Search.web(...).count now returns an int, not a string
+ * many calls were not passing the args argument to #get
+ * Feed.load used to return an open struct with only one method called 'feed' that was a hash. It now returns the feed correctly.
+* Behind the scene changes:
+ * specs
+ * shorter, cleaner code
+ * links to google api doc in rdoc
+ * most classes are now modules
+ * small optimizations
+ * All #get now requires arg (see bug fix)
+
+=== 0.1.0 / 2008-05-19
+
+* Initial Release
View
11 Manifest.txt
@@ -1,11 +0,0 @@
-History.txt
-Manifest.txt
-README.txt
-Rakefile
-lib/googleajax.rb
-lib/googleajax/feed.rb
-lib/googleajax/language.rb
-lib/googleajax/parser.rb
-lib/googleajax/search.rb
-lib/googleajax/version.rb
-test/test_googleajax.rb
View
4 README.rdoc
@@ -55,11 +55,11 @@ Ruby wrapper for Google AJAX API REST interfaces(Feeds, Language and Search).
== REQUIREMENTS:
-* JSON gem to parse responses
+* JSON gem to parse responses, or rails
== INSTALL:
- sudo gem install googleajax --include-dependencies
+ sudo gem install googleajax
== LICENSE:
View
55 Rakefile
@@ -1,17 +1,46 @@
-# -*- ruby -*-
-
require 'rubygems'
-require 'hoe'
-$: << File.dirname(__FILE__) + '/lib'
-require './lib/googleajax.rb'
+require 'rake'
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |gem|
+ gem.name = "googleajax"
+ gem.summary = %Q{Ruby wrapper to the Google AJAX API REST interfaces(Feeds, Language and Search).}
+ #gem.description = %Q{TODO: longer description of your gem}
+ gem.email = "monki@geemus.com"
+ gem.homepage = "http://github.com/geemus/googleajax"
+ gem.authors = ["monki(Wesley Beary)", "Marc-Andre Lafortune"]
+ gem.add_development_dependency "rspec", ">= 1.2.9"
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+ gem.add_dependency 'json', '>= 1.0.0'
+ end
+ Jeweler::GemcutterTasks.new
+rescue LoadError
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
+end
+
+require 'spec/rake/spectask'
+Spec::Rake::SpecTask.new(:spec) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.spec_files = FileList['spec/**/*_spec.rb']
+end
-Hoe.new('GoogleAjax', GoogleAjax::VERSION::STRING) do |p|
- p.rubyforge_name = 'googleajax'
- p.developer('monki(Wesley Beary)', 'monki@geemus.com')
- p.summary = 'Ruby wrapper to the Google AJAX API REST interfaces(Feeds, Language and Search).'
- p.url = 'http://googleajax.rubyforge.com'
- p.remote_rdoc_dir = ''
- p.extra_deps << ['json', '>= 1.0.0']
+Spec::Rake::SpecTask.new(:rcov) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.pattern = 'spec/**/*_spec.rb'
+ spec.rcov = true
end
-# vim: syntax=Ruby
+task :spec => :check_dependencies
+
+task :default => :spec
+
+require 'rake/rdoctask'
+Rake::RDocTask.new do |rdoc|
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
+
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = "googleajax #{version}"
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
View
1  VERSION
@@ -0,0 +1 @@
+0.2.0
View
25 googleajax.gemspec
@@ -1,25 +0,0 @@
-Gem::Specification.new do |s|
- s.name = %q{GoogleAjax}
- s.version = "0.1.0"
-
- s.specification_version = 2 if s.respond_to? :specification_version=
-
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.authors = ["monki(Wesley Beary)"]
- s.date = %q{2008-05-19}
- s.description = %q{Ruby wrapper to the Google AJAX API REST interfaces(Feeds, Language and Search).}
- s.email = ["monki@geemus.com"]
- s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
- s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "lib/googleajax.rb", "lib/googleajax/feed.rb", "lib/googleajax/language.rb", "lib/googleajax/parser.rb", "lib/googleajax/search.rb", "lib/googleajax/version.rb", "test/test_googleajax.rb"]
- s.has_rdoc = true
- s.homepage = %q{http://googleajax.rubyforge.com}
- s.rdoc_options = ["--main", "README.txt"]
- s.require_paths = ["lib"]
- s.rubyforge_project = %q{googleajax}
- s.rubygems_version = %q{1.1.1}
- s.summary = %q{Ruby wrapper to the Google AJAX API REST interfaces(Feeds, Language and Search).}
- s.test_files = ["test/test_googleajax.rb"]
-
- s.add_dependency(%q<json>, [">= 1.0.0"])
- s.add_dependency(%q<hoe>, [">= 1.5.1"])
-end
View
49 lib/googleajax.rb
@@ -4,37 +4,28 @@
require 'rubygems'
require 'json' unless defined?(Rails)
-require 'googleajax/feed'
-require 'googleajax/language'
-require 'googleajax/parser'
-require 'googleajax/search'
-require 'googleajax/version'
+module GoogleAjax
+ require 'googleajax/base' unless const_defined?("Base")
+ require 'googleajax/feed'
+ require 'googleajax/language'
+ require 'googleajax/search'
+ require 'googleajax/parser'
-class GoogleAjax
API_BASE = 'http://ajax.googleapis.com/ajax/services/'
- @@api_key = @@referer = nil
+ class << self
+ attr_accessor :api_key
+ attr_accessor :referer
- def self.api_key
- @@api_key
- end
- def self.api_key=(key)
- @@api_key = key
- end
- def self.referer
- @@referer
- end
- def self.referer=(referer)
- @@referer = referer
- end
-
- def self.get(api, method, query, args = nil)
- raise "You must assign a value to GoogleAjax.referer" unless @@referer
- url = "#{API_BASE}#{api}/"
- url += "#{method}?"
- url += "&q=#{CGI::escape(query)}"
- url += "&key=#{api_key}" if api_key
- url += "&" + args.collect {|key, value| "#{key}=#{value}"}.join('&') if args && !args.empty?
- data = open(url, "Referer" => @@referer).read
- Parser.parse(api, method, data)
+ # Api doc is at http://code.google.com/apis/ajaxsearch/documentation/reference.html#_intro_fonje
+ def get(api, method, query, args = nil)
+ raise "You must assign a value to GoogleAjax.referer" unless referer
+ url = "#{API_BASE}#{api}/"
+ url += "#{method}?"
+ url += "&q=#{CGI::escape(query)}"
+ url += "&key=#{api_key}" if api_key
+ url += "&" + args.collect {|key, value| "#{key}=#{value}"}.join('&') if args && !args.empty?
+ data = open(url, "Referer" => referer).read
+ Parser.parse(api, method, data)
+ end
end
end
View
15 lib/googleajax/as_hash.rb
@@ -0,0 +1,15 @@
+# Include this file instead of googleajax so that results are simply hashes
+
+module GoogleAjax
+ class Base < Hash
+ def initialize(h)
+ super()
+ replace(h)
+ end
+
+ def self.remap(h)
+ end
+ end
+end
+
+require 'googleajax'
View
25 lib/googleajax/base.rb
@@ -0,0 +1,25 @@
+module GoogleAjax
+ class Base < OpenStruct
+ def [](key)
+ send(key)
+ end
+
+ def []=(key, value)
+ send("#{key}=", value)
+ end
+
+ def self.remap(h)
+ define_method(:initialize) do |arg|
+ super(arg)
+ h.each do |key, klass|
+ case self[key]
+ when Array
+ self[key] = self[key].map(&klass.method(:new))
+ when Hash
+ self[key] = klass.new(self[key])
+ end
+ end
+ end
+ end
+ end
+end
View
43 lib/googleajax/feed.rb
@@ -1,38 +1,35 @@
-class GoogleAjax
- class Feed
+module GoogleAjax
+ module Feed
FEED_VERSION = 1.0
- def self.get(method, query, args = {})
- args = { :v => FEED_VERSION }.merge!(args)
+ # Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_intro_fonje
+ def self.get(method, query, args)
+ args = { :v => FEED_VERSION }.merge(args)
GoogleAjax::get(:feed, method, query, args)
end
-
+
# will return a list of feeds that match the given query
+ # Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_fonje_find
def self.find(query, args = {})
- self.get(:find, query)
+ self.get(:find, query, args)
end
# downloads this feed from Google's servers
- # Optional: args { :num => number of entries to download(default is 4, maximum is 100) }
- def self.load(query, args = {})
- self.get(:load, query, args)
+ # Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_fonje_load
+ def self.load(url, args = {})
+ self.get(:load, url, args)
end
-
+
# will return the associated feed if it exists for a given url
- def self.lookup(query, args = {})
- self.get(:lookup, query)
+ # Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_intro_fonje
+ def self.lookup(url, args = {})
+ self.get(:lookup, url, args)
end
-
- class Entry < OpenStruct
- def initialize(data)
- super(data)
- end
+
+ class Entry < Base
end
-
- class Feed < OpenStruct
- def initialize(data)
- super(data)
- self.entries = entries.collect {|data| Entry.new(data)} if entries
- end
+
+ class Feed < Base
+ remap :entries => Entry
end
end
end
View
27 lib/googleajax/language.rb
@@ -1,36 +1,29 @@
-class GoogleAjax
- class Language
+module GoogleAjax
+ module Language
LANGUAGE_VERSION = 1.0
- def self.get(method, query, args = {})
- args = { :v => LANGUAGE_VERSION }.merge!(args)
+ def self.get(method, query, args)
+ args = { :v => LANGUAGE_VERSION }.merge(args)
GoogleAjax::get(:language, method, query, args)
end
# will return the language code that describes the language of the given text
def self.detect(query, args = {})
- self.get(:detect, query)
+ self.get(:detect, query, args)
end
# will return translated text for the given text supplied, matching the destination language.
def self.translate(query, source, destination, args = {})
- args = { :langpair => "#{source}%7C#{destination}"}.merge!(args)
+ args = { :langpair => "#{source}%7C#{destination}"}.merge(args)
self.get(:translate, query, args)
end
- class Language < OpenStruct
- def initialize(data)
- super(data)
- end
-
+ class Language < Base
def name
- LANGUAGES.invert[self.language]
+ (@@lang_cache ||= LANGUAGES.invert)[self.language]
end
end
- class Translation < OpenStruct
- def initialize(data)
- super(data)
- end
+ class Translation < Base
end
LANGUAGES =
@@ -77,6 +70,6 @@ def initialize(data)
'UKRAINIAN' => 'uk',
'VIETNAMESE' => 'vi',
'UNKNOWN' => ''
- }
+ }
end
end
View
100 lib/googleajax/parser.rb
@@ -1,94 +1,38 @@
-class GoogleAjax
- class Parser
+module GoogleAjax
+ module Parser
def self.parse(api, method, data)
- if defined? Rails
- data = ActiveSupport::JSON::decode(data)
+ data = if defined? Rails
+ ActiveSupport::JSON::decode(data)
else
- data = JSON.parse(data)
+ JSON.parse(data)
end
- Errors.process(data)
- parser = Parser::PARSERS[api][method]
- parser.process(data['responseData'])
+ process_errors(data)
+ parser = PARSERS[api][method]
+ response = data['responseData']
+ parser.is_a?(Symbol) ? send(parser, response) : parser.new(response) if response
end
- end
- class FeedFind < Parser#:nodoc:
- def self.process(data)
- data['entries'].collect {|data| GoogleAjax::Feed::Feed.new(data)} if data
- end
- end
- class FeedLoad < Parser#:nodoc:
- def self.process(data)
- GoogleAjax::Feed::Feed.new(data['feed']) if data
- end
- end
- class FeedLookup < Parser#:nodoc:
- def self.process(data)
- GoogleAjax::Feed::Feed.new(data) if data
+ def self.process_errors(data)
+ status = data['responseStatus']
+ unless (200..206).include? status
+ raise StandardError, data['responseDetails']
+ end
end
- end
- class LanguageDetect < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Language::Language.new(data) if data
- end
- end
- class LanguageTranslate < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Language::Translation.new(data) if data
+ def self.parse_feed_list(data)
+ data['entries'].map(&Feed::Feed.method(:new))
end
- end
- class SearchBlogs < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
- end
- end
- class SearchBooks < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
- end
- end
- class SearchImages < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
- end
- end
- class SearchLocal < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
- end
- end
- class SearchNews < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
- end
- end
- class SearchVideo < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
+ def self.parse_one_feed(data)
+ Feed::Feed.new(data['feed'])
end
- end
- class SearchWeb < Parser#:nodoc
- def self.process(data)
- GoogleAjax::Search::Results.new(data) if data
- end
- end
- class Parser
PARSERS = {
- :feed => { :find => FeedFind, :load => FeedLoad, :lookup => FeedLookup },
- :language => { :detect => LanguageDetect, :translate => LanguageTranslate, },
- :search => { :blogs => SearchBlogs, :books => SearchBooks, :images => SearchImages, :local => SearchLocal, :news => SearchNews, :video => SearchVideo, :web => SearchWeb }
+ :feed => { :find => :parse_feed_list, :load => :parse_one_feed, :lookup => Feed::Feed },
+ :language => { :detect => Language::Language, :translate => Language::Translation },
+ :search => { :blogs => Search::Results, :books => Search::Results, :images => Search::Results, :local => Search::Results,
+ :news => Search::Results, :video => Search::Results, :web => Search::Results }
}
- end
- class Errors
- def self.process(data)
- status = data['responseStatus']
- unless [200, 201, 202, 203, 204, 205, 206].include? status
- raise StandardError.new(data['responseDetails'])
- end
- end
end
end
View
69 lib/googleajax/search.rb
@@ -1,69 +1,66 @@
-class GoogleAjax
- class Search
+module GoogleAjax
+ module Search
SEARCH_VERSION = 1.0
- def self.get(method, query, args = {})
- args = { :v => SEARCH_VERSION }.merge!(args)
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_web
+ def self.get(method, query, args)
+ args = { :v => SEARCH_VERSION }.merge(args)
GoogleAjax::get(:search, method, query, args)
end
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_blog
def self.blogs(query, args = {})
self.get(:blogs, query, args)
end
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_book
def self.books(query, args = {})
self.get(:books, query, args)
end
-
+
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_image
def self.images(query, args = {})
self.get(:images, query, args)
end
-
+
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_local
def self.local(query, latitude, longitude, args = {})
- args = { :sll => "#{latitude},#{longitude}" }.merge!(args)
+ args = { :sll => "#{latitude},#{longitude}" }.merge(args)
self.get(:local, query, args)
end
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_news
def self.news(query, args = {})
self.get(:news, query, args)
end
-
+
+ # Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_video
def self.video(query, args = {})
self.get(:video, query, args)
end
-
+
+ # http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_web
def self.web(query, args = {})
self.get(:web, query, args)
end
-
- class Results < OpenStruct
- def initialize(data)
- super(data)
- self.results = results.collect {|data| Result.new(data)}
- self.cursor = Cursor.new(cursor) if self.cursor
- end
-
- def count
- self.cursor.estimatedResultCount
- end
+
+ class Result < Base
end
-
- class Result < OpenStruct
- def initialize(data)
- super(data)
- end
+
+ class Page < Base
end
-
- class Cursor < OpenStruct
- def initialize(data)
- super(data)
- self.pages = pages.collect {|data| Page.new(data)}
- end
+
+ class Cursor < Base
+ remap :pages => Page
end
-
- class Page < OpenStruct
- def initialize(data)
- super(data)
+
+ class Results < Base
+ remap :results => Result,
+ :cursor => Cursor
+
+ def count
+ self['cursor']['estimatedResultCount'].to_i
end
- end
+ end
+
end
end
View
8 lib/googleajax/version.rb
@@ -1,8 +0,0 @@
-class GoogleAjax
- module VERSION #:nodoc:
- MAJOR = 0
- MINOR = 1
- TINY = 0
- STRING = [MAJOR, MINOR, TINY].join('.')
- end
-end
View
15 spec/googleajax_as_hash_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+require File.expand_path(File.dirname(__FILE__) + '/googleajax_common')
+
+require 'googleajax/as_hash'
+
+describe "GoogleAjax/as_hash" do
+ it_should_behave_like "GoogleAjax"
+
+ it "returns results as a hash" do
+ GoogleAjax.referer = "http://example.com"
+ response = GoogleAjax::Search.web("apple", :rsz => :large)
+ response.is_a? Hash
+ response['cursor'].is_a? Hash
+ end
+end
View
93 spec/googleajax_common.rb
@@ -0,0 +1,93 @@
+# encoding:utf-8
+shared_examples_for "GoogleAjax" do
+ it "requires a referer" do
+ GoogleAjax.referer = nil
+ lambda{GoogleAjax::Search.web("testing")}.should raise_error
+ end
+
+ describe "::Search" do
+ describe ".web" do
+ before :each do
+ GoogleAjax.referer = "http://example.com"
+ @response = GoogleAjax::Search.web("apple", :rsz => :large)
+ end
+
+ it "returns the expected results" do
+ @response['results'].count{|result| result['url'] =~ /http:(.*).apple.com/}.should >= 4
+ end
+ end
+
+ {
+ :blogs => 100_000,
+ :books => 10_000,
+ :images => 10_000,
+ :video => 10_000,
+ :web => 1_000_000,
+ :local => [100, 48.8565, 2.3509]
+ }.each do |method, (min, *args)|
+ describe ".#{method}" do
+ before :each do
+ GoogleAjax.referer = "http://example.com"
+ @response_small = GoogleAjax::Search.send(method, "ruby", *args)
+ end
+
+ it "takes options into account" do
+ @response_large = GoogleAjax::Search.send(method, "ruby", *(args+[{:rsz => :large}]))
+ @response_large['results'].size.should > @response_small['results'].size
+ end unless method == :blogs # Google doesn't seem to support this option for blogs???
+
+ it "returns an approximate count of hits" do
+ @response_small.count.should > min
+ end
+ end
+ end
+ end
+
+ describe "::Language" do
+ before :each do
+ GoogleAjax.referer = "http://example.com"
+ end
+
+ describe ".detect" do
+ it "returns the right language" do
+ GoogleAjax::Language.detect("What's up folks")['language'].should == "en"
+ GoogleAjax::Language.detect("Montréal est une ville incroyable")['language'].should == "fr"
+ end
+ end
+
+ describe ".translate" do
+ it "does an approximate translation" do
+ GoogleAjax::Language.translate("Ruby rocks", "en", "fr")['translatedText'].should == "Ruby roches"
+ end
+ end
+ end
+
+ describe "::Feed" do
+ before :each do
+ GoogleAjax.referer = "http://example.com"
+ end
+
+ describe ".find" do
+ it "returns the right feeds" do
+ feeds = GoogleAjax::Feed.find("Ruby")
+ feeds.size.should == 10
+ feeds.any?{|result| result['url'] == "http://www.ruby-lang.org/en/feeds/news.rss"}.should be_true
+ end
+ end
+
+ describe ".load" do
+ it "loads entries of a feed" do
+ feed = GoogleAjax::Feed.load('http://digg.com/rss/index.xml')
+ feed['title'].should == "digg.com: Stories / Popular"
+ feed['entries'].size.should == 4
+ end
+ end
+
+ describe ".lookup" do
+ it "returns the feed associated with a URL" do
+ feed = GoogleAjax::Feed.lookup("http://digg.com/")
+ feed['url'].should == "http://feeds.digg.com/digg/popular.rss"
+ end
+ end
+ end
+end
View
15 spec/googleajax_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+require File.expand_path(File.dirname(__FILE__) + '/googleajax_common')
+
+require 'googleajax'
+
+describe "GoogleAjax (standard)" do
+ it_should_behave_like "GoogleAjax"
+
+ it "returns results as an OpenStuct" do
+ GoogleAjax.referer = "http://example.com"
+ response = GoogleAjax::Search.web("apple", :rsz => :large)
+ response.is_a? OpenStruct
+ response.cursor.is_a? OpenStruct
+ end
+end
View
1  spec/spec.opts
@@ -0,0 +1 @@
+--color
View
8 spec/spec_helper.rb
@@ -0,0 +1,8 @@
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+require 'spec'
+require 'spec/autorun'
+
+Spec::Runner.configure do |config|
+
+end
View
0  test/test_googleajax.rb
No changes.
Please sign in to comment.
Something went wrong with that request. Please try again.