googleajax 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +19 -3
- data/README.txt +47 -20
- data/Rakefile +42 -13
- data/VERSION +1 -0
- data/lib/googleajax.rb +31 -0
- data/lib/googleajax/as_hash.rb +15 -0
- data/lib/googleajax/base.rb +25 -0
- data/lib/googleajax/feed.rb +35 -0
- data/lib/{google_ajax → googleajax}/language.rb +10 -17
- data/lib/googleajax/parser.rb +38 -0
- data/lib/googleajax/search.rb +66 -0
- data/spec/googleajax_as_hash_spec.rb +15 -0
- data/spec/googleajax_common.rb +93 -0
- data/spec/googleajax_spec.rb +15 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +8 -0
- metadata +36 -27
- data/Manifest.txt +0 -11
- data/lib/google_ajax.rb +0 -41
- data/lib/google_ajax/feed.rb +0 -38
- data/lib/google_ajax/parser.rb +0 -90
- data/lib/google_ajax/search.rb +0 -69
- data/lib/google_ajax/version.rb +0 -8
- data/test/test_google_ajax.rb +0 -0
data/History.txt
CHANGED
@@ -1,6 +1,22 @@
|
|
1
|
-
===
|
1
|
+
=== 0.2.0 / 2009-11-17
|
2
2
|
|
3
|
-
*
|
3
|
+
* New features:
|
4
|
+
* results can use [] and []= for lookup and seting
|
5
|
+
* allows results to be open structs (default) or hash (by requiring 'googleajax/as_hash' instead)
|
4
6
|
|
5
|
-
|
7
|
+
* bug fixes:
|
8
|
+
* Search.web(...).count now returns an int, not a string
|
9
|
+
* many calls were not passing the args argument to #get
|
10
|
+
* Feed.load used to return an open struct with only one method called 'feed' that was a hash. It now returns the feed correctly.
|
6
11
|
|
12
|
+
* Behind the scene changes:
|
13
|
+
* specs
|
14
|
+
* shorter, cleaner code
|
15
|
+
* links to google api doc in rdoc
|
16
|
+
* most classes are now modules
|
17
|
+
* small optimizations
|
18
|
+
* All #get now requires arg (see bug fix)
|
19
|
+
|
20
|
+
=== 0.1.0 / 2008-05-19
|
21
|
+
|
22
|
+
* Initial Release
|
data/README.txt
CHANGED
@@ -5,40 +5,67 @@
|
|
5
5
|
|
6
6
|
== DESCRIPTION:
|
7
7
|
|
8
|
-
Ruby wrapper
|
8
|
+
Ruby wrapper for Google AJAX API REST interfaces(Feeds, Language and Search).
|
9
9
|
|
10
10
|
== SYNOPSIS:
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
12
|
+
# First, setup referer:
|
13
|
+
GoogleAjax.referer = [your domain name here]
|
14
|
+
|
15
|
+
# Optionally, you can set an api_key:
|
16
|
+
GoogleAjax.api_key = [your api key here]
|
17
|
+
|
18
|
+
=== Now you are set to go, so here are a few examples:
|
19
|
+
|
20
|
+
# Find top 10 feeds for 'ruby'
|
21
|
+
GoogleAjax::Feed.find('ruby')
|
22
|
+
|
23
|
+
# Load 4 most recent entries from 'http://monki.geemus.com/feed/atom.xml'
|
24
|
+
GoogleAjax::Feed.load('http://monki.geemus.com/feed/atom.xml')
|
25
|
+
|
26
|
+
# Find feed for 'http://monki.geemus.com'
|
27
|
+
GoogleAjax::Feed.lookup('http://monki.geemus.com')
|
28
|
+
|
29
|
+
# Find the language of the string 'Ciao mondo'
|
30
|
+
GoogleAjax::Language.detect('Ciao mondo')
|
31
|
+
|
32
|
+
# Translate 'Hello world' to italian
|
33
|
+
GoogleAjax::Language.translate('Hello world', 'en', 'it')
|
34
|
+
|
35
|
+
# Find top 4 blogs for 'ruby'
|
36
|
+
GoogleAjax::Search.blogs('ruby')
|
37
|
+
|
38
|
+
# Find top 4 books for 'ruby'
|
39
|
+
GoogleAjax::Search.books('ruby')
|
40
|
+
|
41
|
+
# Find top 4 images for 'ruby'
|
42
|
+
GoogleAjax::Search.images('ruby')
|
43
|
+
|
44
|
+
# Find top 4 local results for 'ruby' at latitude 48.8565, longitude 2.3509
|
45
|
+
GoogleAjax::Search.local('ruby', 48.8565, 2.3509)
|
46
|
+
|
47
|
+
# Find top 4 news results for 'ruby'
|
48
|
+
GoogleAjax::Search.news('ruby')
|
49
|
+
|
50
|
+
# Find top 4 video results for 'ruby'
|
51
|
+
GoogleAjax::Search.video('ruby')
|
52
|
+
|
53
|
+
# Find top 4 web page results for 'Hello world'
|
54
|
+
GoogleAjax::Search.web('Hello world')
|
28
55
|
|
29
56
|
== REQUIREMENTS:
|
30
57
|
|
31
|
-
* JSON gem to parse
|
58
|
+
* JSON gem to parse responses, or rails
|
32
59
|
|
33
60
|
== INSTALL:
|
34
61
|
|
35
|
-
|
62
|
+
sudo gem install googleajax
|
36
63
|
|
37
64
|
== LICENSE:
|
38
65
|
|
39
66
|
(The MIT License)
|
40
67
|
|
41
|
-
Copyright (c)
|
68
|
+
Copyright (c) 2009 {geemus (Wesley Beary)}[http://github.com/geemus]
|
42
69
|
|
43
70
|
Permission is hereby granted, free of charge, to any person obtaining
|
44
71
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,17 +1,46 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
|
3
1
|
require 'rubygems'
|
4
|
-
require '
|
5
|
-
|
6
|
-
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "googleajax"
|
8
|
+
gem.summary = %Q{Ruby wrapper to the Google AJAX API REST interfaces(Feeds, Language and Search).}
|
9
|
+
#gem.description = %Q{TODO: longer description of your gem}
|
10
|
+
gem.email = "me@geemus.com"
|
11
|
+
gem.homepage = "http://github.com/geemus/googleajax"
|
12
|
+
gem.authors = ["geemus(Wesley Beary)", "Marc-Andre Lafortune"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
gem.add_dependency 'json', '>= 1.0.0'
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
+
spec.libs << 'lib' << 'spec'
|
25
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
+
end
|
7
27
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
p.url = 'http://googleajax.rubyforge.com'
|
13
|
-
p.remote_rdoc_dir = ''
|
14
|
-
p.extra_deps << ['json', '>= 1.0.0']
|
28
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
+
spec.rcov = true
|
15
32
|
end
|
16
33
|
|
17
|
-
|
34
|
+
task :spec => :check_dependencies
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
41
|
+
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "googleajax #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/lib/googleajax.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'json' unless defined?(Rails)
|
6
|
+
|
7
|
+
module GoogleAjax
|
8
|
+
require 'googleajax/base' unless const_defined?("Base")
|
9
|
+
require 'googleajax/feed'
|
10
|
+
require 'googleajax/language'
|
11
|
+
require 'googleajax/search'
|
12
|
+
require 'googleajax/parser'
|
13
|
+
|
14
|
+
API_BASE = 'http://ajax.googleapis.com/ajax/services/'
|
15
|
+
class << self
|
16
|
+
attr_accessor :api_key
|
17
|
+
attr_accessor :referer
|
18
|
+
|
19
|
+
# Api doc is at http://code.google.com/apis/ajaxsearch/documentation/reference.html#_intro_fonje
|
20
|
+
def get(api, method, query, args = nil)
|
21
|
+
raise "You must assign a value to GoogleAjax.referer" unless referer
|
22
|
+
url = "#{API_BASE}#{api}/"
|
23
|
+
url += "#{method}?"
|
24
|
+
url += "&q=#{CGI::escape(query)}"
|
25
|
+
url += "&key=#{api_key}" if api_key
|
26
|
+
url += "&" + args.collect {|key, value| "#{key}=#{value}"}.join('&') if args && !args.empty?
|
27
|
+
data = open(url, "Referer" => referer).read
|
28
|
+
Parser.parse(api, method, data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GoogleAjax
|
2
|
+
class Base < OpenStruct
|
3
|
+
def [](key)
|
4
|
+
send(key)
|
5
|
+
end
|
6
|
+
|
7
|
+
def []=(key, value)
|
8
|
+
send("#{key}=", value)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.remap(h)
|
12
|
+
define_method(:initialize) do |arg|
|
13
|
+
super(arg)
|
14
|
+
h.each do |key, klass|
|
15
|
+
case self[key]
|
16
|
+
when Array
|
17
|
+
self[key] = self[key].map(&klass.method(:new))
|
18
|
+
when Hash
|
19
|
+
self[key] = klass.new(self[key])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module GoogleAjax
|
2
|
+
module Feed
|
3
|
+
FEED_VERSION = 1.0
|
4
|
+
# Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_intro_fonje
|
5
|
+
def self.get(method, query, args)
|
6
|
+
args = { :v => FEED_VERSION }.merge(args)
|
7
|
+
GoogleAjax::get(:feed, method, query, args)
|
8
|
+
end
|
9
|
+
|
10
|
+
# will return a list of feeds that match the given query
|
11
|
+
# Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_fonje_find
|
12
|
+
def self.find(query, args = {})
|
13
|
+
self.get(:find, query, args)
|
14
|
+
end
|
15
|
+
|
16
|
+
# downloads this feed from Google's servers
|
17
|
+
# Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_fonje_load
|
18
|
+
def self.load(url, args = {})
|
19
|
+
self.get(:load, url, args)
|
20
|
+
end
|
21
|
+
|
22
|
+
# will return the associated feed if it exists for a given url
|
23
|
+
# Arguments: http://code.google.com/apis/ajaxfeeds/documentation/reference.html#_intro_fonje
|
24
|
+
def self.lookup(url, args = {})
|
25
|
+
self.get(:lookup, url, args)
|
26
|
+
end
|
27
|
+
|
28
|
+
class Entry < Base
|
29
|
+
end
|
30
|
+
|
31
|
+
class Feed < Base
|
32
|
+
remap :entries => Entry
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,36 +1,29 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module GoogleAjax
|
2
|
+
module Language
|
3
3
|
LANGUAGE_VERSION = 1.0
|
4
|
-
def self.get(method, query, args
|
5
|
-
args = { :v => LANGUAGE_VERSION }.merge
|
4
|
+
def self.get(method, query, args)
|
5
|
+
args = { :v => LANGUAGE_VERSION }.merge(args)
|
6
6
|
GoogleAjax::get(:language, method, query, args)
|
7
7
|
end
|
8
8
|
|
9
9
|
# will return the language code that describes the language of the given text
|
10
10
|
def self.detect(query, args = {})
|
11
|
-
self.get(:detect, query)
|
11
|
+
self.get(:detect, query, args)
|
12
12
|
end
|
13
13
|
|
14
14
|
# will return translated text for the given text supplied, matching the destination language.
|
15
15
|
def self.translate(query, source, destination, args = {})
|
16
|
-
args = { :langpair => "#{source}%7C#{destination}"}.merge
|
16
|
+
args = { :langpair => "#{source}%7C#{destination}"}.merge(args)
|
17
17
|
self.get(:translate, query, args)
|
18
18
|
end
|
19
19
|
|
20
|
-
class Language <
|
21
|
-
def initialize(data)
|
22
|
-
super(data)
|
23
|
-
end
|
24
|
-
|
20
|
+
class Language < Base
|
25
21
|
def name
|
26
|
-
LANGUAGES.invert[self.language]
|
22
|
+
(@@lang_cache ||= LANGUAGES.invert)[self.language]
|
27
23
|
end
|
28
24
|
end
|
29
25
|
|
30
|
-
class Translation <
|
31
|
-
def initialize(data)
|
32
|
-
super(data)
|
33
|
-
end
|
26
|
+
class Translation < Base
|
34
27
|
end
|
35
28
|
|
36
29
|
LANGUAGES =
|
@@ -77,6 +70,6 @@ class GoogleAjax
|
|
77
70
|
'UKRAINIAN' => 'uk',
|
78
71
|
'VIETNAMESE' => 'vi',
|
79
72
|
'UNKNOWN' => ''
|
80
|
-
}
|
73
|
+
}
|
81
74
|
end
|
82
75
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GoogleAjax
|
2
|
+
module Parser
|
3
|
+
def self.parse(api, method, data)
|
4
|
+
data = if defined? Rails
|
5
|
+
ActiveSupport::JSON::decode(data)
|
6
|
+
else
|
7
|
+
JSON.parse(data)
|
8
|
+
end
|
9
|
+
process_errors(data)
|
10
|
+
parser = PARSERS[api][method]
|
11
|
+
response = data['responseData']
|
12
|
+
parser.is_a?(Symbol) ? send(parser, response) : parser.new(response) if response
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.process_errors(data)
|
16
|
+
status = data['responseStatus']
|
17
|
+
unless (200..206).include? status
|
18
|
+
raise StandardError, data['responseDetails']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse_feed_list(data)
|
23
|
+
data['entries'].map(&Feed::Feed.method(:new))
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.parse_one_feed(data)
|
27
|
+
Feed::Feed.new(data['feed'])
|
28
|
+
end
|
29
|
+
|
30
|
+
PARSERS = {
|
31
|
+
:feed => { :find => :parse_feed_list, :load => :parse_one_feed, :lookup => Feed::Feed },
|
32
|
+
:language => { :detect => Language::Language, :translate => Language::Translation },
|
33
|
+
:search => { :blogs => Search::Results, :books => Search::Results, :images => Search::Results, :local => Search::Results,
|
34
|
+
:news => Search::Results, :video => Search::Results, :web => Search::Results }
|
35
|
+
}
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module GoogleAjax
|
2
|
+
module Search
|
3
|
+
SEARCH_VERSION = 1.0
|
4
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_web
|
5
|
+
def self.get(method, query, args)
|
6
|
+
args = { :v => SEARCH_VERSION }.merge(args)
|
7
|
+
GoogleAjax::get(:search, method, query, args)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_blog
|
11
|
+
def self.blogs(query, args = {})
|
12
|
+
self.get(:blogs, query, args)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_book
|
16
|
+
def self.books(query, args = {})
|
17
|
+
self.get(:books, query, args)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_image
|
21
|
+
def self.images(query, args = {})
|
22
|
+
self.get(:images, query, args)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_local
|
26
|
+
def self.local(query, latitude, longitude, args = {})
|
27
|
+
args = { :sll => "#{latitude},#{longitude}" }.merge(args)
|
28
|
+
self.get(:local, query, args)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_news
|
32
|
+
def self.news(query, args = {})
|
33
|
+
self.get(:news, query, args)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Arguments: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_video
|
37
|
+
def self.video(query, args = {})
|
38
|
+
self.get(:video, query, args)
|
39
|
+
end
|
40
|
+
|
41
|
+
# http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_web
|
42
|
+
def self.web(query, args = {})
|
43
|
+
self.get(:web, query, args)
|
44
|
+
end
|
45
|
+
|
46
|
+
class Result < Base
|
47
|
+
end
|
48
|
+
|
49
|
+
class Page < Base
|
50
|
+
end
|
51
|
+
|
52
|
+
class Cursor < Base
|
53
|
+
remap :pages => Page
|
54
|
+
end
|
55
|
+
|
56
|
+
class Results < Base
|
57
|
+
remap :results => Result,
|
58
|
+
:cursor => Cursor
|
59
|
+
|
60
|
+
def count
|
61
|
+
self['cursor']['estimatedResultCount'].to_i
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/googleajax_common')
|
3
|
+
|
4
|
+
require 'googleajax/as_hash'
|
5
|
+
|
6
|
+
describe "GoogleAjax/as_hash" do
|
7
|
+
it_should_behave_like "GoogleAjax"
|
8
|
+
|
9
|
+
it "returns results as a hash" do
|
10
|
+
GoogleAjax.referer = "http://example.com"
|
11
|
+
response = GoogleAjax::Search.web("apple", :rsz => :large)
|
12
|
+
response.is_a? Hash
|
13
|
+
response['cursor'].is_a? Hash
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
shared_examples_for "GoogleAjax" do
|
3
|
+
it "requires a referer" do
|
4
|
+
GoogleAjax.referer = nil
|
5
|
+
lambda{GoogleAjax::Search.web("testing")}.should raise_error
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "::Search" do
|
9
|
+
describe ".web" do
|
10
|
+
before :each do
|
11
|
+
GoogleAjax.referer = "http://example.com"
|
12
|
+
@response = GoogleAjax::Search.web("apple", :rsz => :large)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns the expected results" do
|
16
|
+
@response['results'].select{|result| result['url'] =~ /http:(.*).apple.com/}.size.should >= 4
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
{
|
21
|
+
:blogs => 100_000,
|
22
|
+
:books => 10_000,
|
23
|
+
:images => 10_000,
|
24
|
+
:video => 10_000,
|
25
|
+
:web => 1_000_000,
|
26
|
+
:local => [100, 48.8565, 2.3509]
|
27
|
+
}.each do |method, (min, *args)|
|
28
|
+
describe ".#{method}" do
|
29
|
+
before :each do
|
30
|
+
GoogleAjax.referer = "http://example.com"
|
31
|
+
@response_small = GoogleAjax::Search.send(method, "ruby", *args)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "takes options into account" do
|
35
|
+
@response_large = GoogleAjax::Search.send(method, "ruby", *(args+[{:rsz => :large}]))
|
36
|
+
@response_large['results'].size.should > @response_small['results'].size
|
37
|
+
end unless method == :blogs # Google doesn't seem to support this option for blogs???
|
38
|
+
|
39
|
+
it "returns an approximate count of hits" do
|
40
|
+
@response_small.count.should > min
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "::Language" do
|
47
|
+
before :each do
|
48
|
+
GoogleAjax.referer = "http://example.com"
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".detect" do
|
52
|
+
it "returns the right language" do
|
53
|
+
GoogleAjax::Language.detect("What's up folks")['language'].should == "en"
|
54
|
+
GoogleAjax::Language.detect("Montréal est une ville incroyable")['language'].should == "fr"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe ".translate" do
|
59
|
+
it "does an approximate translation" do
|
60
|
+
GoogleAjax::Language.translate("Ruby rocks", "en", "fr")['translatedText'].should == "Ruby roches"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "::Feed" do
|
66
|
+
before :each do
|
67
|
+
GoogleAjax.referer = "http://example.com"
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ".find" do
|
71
|
+
it "returns the right feeds" do
|
72
|
+
feeds = GoogleAjax::Feed.find("Ruby")
|
73
|
+
feeds.size.should == 10
|
74
|
+
feeds.any?{|result| result['url'] == "http://www.ruby-lang.org/en/feeds/news.rss"}.should be_true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".load" do
|
79
|
+
it "loads entries of a feed" do
|
80
|
+
feed = GoogleAjax::Feed.load('http://digg.com/rss/index.xml')
|
81
|
+
feed['title'].should == "digg.com: Stories / Popular"
|
82
|
+
feed['entries'].size.should == 4
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe ".lookup" do
|
87
|
+
it "returns the feed associated with a URL" do
|
88
|
+
feed = GoogleAjax::Feed.lookup("http://digg.com/")
|
89
|
+
feed['url'].should == "http://feeds.digg.com/digg/popular.rss"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/googleajax_common')
|
3
|
+
|
4
|
+
require 'googleajax'
|
5
|
+
|
6
|
+
describe "GoogleAjax (standard)" do
|
7
|
+
it_should_behave_like "GoogleAjax"
|
8
|
+
|
9
|
+
it "returns results as an OpenStuct" do
|
10
|
+
GoogleAjax.referer = "http://example.com"
|
11
|
+
response = GoogleAjax::Search.web("apple", :rsz => :large)
|
12
|
+
response.is_a? OpenStruct
|
13
|
+
response.cursor.is_a? OpenStruct
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,64 +1,70 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googleajax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- geemus(Wesley Beary)
|
8
|
+
- Marc-Andre Lafortune
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date:
|
13
|
+
date: 2009-11-17 00:00:00 -08:00
|
13
14
|
default_executable:
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
17
|
+
name: rspec
|
18
|
+
type: :development
|
17
19
|
version_requirement:
|
18
20
|
version_requirements: !ruby/object:Gem::Requirement
|
19
21
|
requirements:
|
20
22
|
- - ">="
|
21
23
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.
|
24
|
+
version: 1.2.9
|
23
25
|
version:
|
24
26
|
- !ruby/object:Gem::Dependency
|
25
|
-
name:
|
27
|
+
name: json
|
28
|
+
type: :runtime
|
26
29
|
version_requirement:
|
27
30
|
version_requirements: !ruby/object:Gem::Requirement
|
28
31
|
requirements:
|
29
32
|
- - ">="
|
30
33
|
- !ruby/object:Gem::Version
|
31
|
-
version: 1.
|
34
|
+
version: 1.0.0
|
32
35
|
version:
|
33
|
-
description:
|
34
|
-
email:
|
35
|
-
- monki@geemus.com
|
36
|
+
description:
|
37
|
+
email: me@geemus.com
|
36
38
|
executables: []
|
37
39
|
|
38
40
|
extensions: []
|
39
41
|
|
40
42
|
extra_rdoc_files:
|
41
|
-
- History.txt
|
42
|
-
- Manifest.txt
|
43
43
|
- README.txt
|
44
44
|
files:
|
45
45
|
- History.txt
|
46
|
-
- Manifest.txt
|
47
46
|
- README.txt
|
48
47
|
- Rakefile
|
49
|
-
-
|
50
|
-
- lib/
|
51
|
-
- lib/
|
52
|
-
- lib/
|
53
|
-
- lib/
|
54
|
-
- lib/
|
55
|
-
-
|
48
|
+
- VERSION
|
49
|
+
- lib/googleajax.rb
|
50
|
+
- lib/googleajax/as_hash.rb
|
51
|
+
- lib/googleajax/base.rb
|
52
|
+
- lib/googleajax/feed.rb
|
53
|
+
- lib/googleajax/language.rb
|
54
|
+
- lib/googleajax/parser.rb
|
55
|
+
- lib/googleajax/search.rb
|
56
|
+
- spec/googleajax_as_hash_spec.rb
|
57
|
+
- spec/googleajax_common.rb
|
58
|
+
- spec/googleajax_spec.rb
|
59
|
+
- spec/spec.opts
|
60
|
+
- spec/spec_helper.rb
|
56
61
|
has_rdoc: true
|
57
|
-
homepage: http://
|
62
|
+
homepage: http://github.com/geemus/googleajax
|
63
|
+
licenses: []
|
64
|
+
|
58
65
|
post_install_message:
|
59
66
|
rdoc_options:
|
60
|
-
- --
|
61
|
-
- README.txt
|
67
|
+
- --charset=UTF-8
|
62
68
|
require_paths:
|
63
69
|
- lib
|
64
70
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -75,10 +81,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
81
|
version:
|
76
82
|
requirements: []
|
77
83
|
|
78
|
-
rubyforge_project:
|
79
|
-
rubygems_version: 1.
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.3.5
|
80
86
|
signing_key:
|
81
|
-
specification_version:
|
87
|
+
specification_version: 3
|
82
88
|
summary: Ruby wrapper to the Google AJAX API REST interfaces(Feeds, Language and Search).
|
83
89
|
test_files:
|
84
|
-
-
|
90
|
+
- spec/googleajax_as_hash_spec.rb
|
91
|
+
- spec/googleajax_common.rb
|
92
|
+
- spec/googleajax_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
data/Manifest.txt
DELETED
data/lib/google_ajax.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
require 'open-uri'
|
3
|
-
require 'ostruct'
|
4
|
-
require 'rubygems'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
require 'google_ajax/feed'
|
8
|
-
require 'google_ajax/language'
|
9
|
-
require 'google_ajax/parser'
|
10
|
-
require 'google_ajax/search'
|
11
|
-
require 'google_ajax/version'
|
12
|
-
|
13
|
-
class GoogleAjax
|
14
|
-
API_BASE = 'http://ajax.googleapis.com/ajax/services/'
|
15
|
-
@@api_key = @@referer = nil
|
16
|
-
|
17
|
-
def self.api_key
|
18
|
-
@@api_key
|
19
|
-
end
|
20
|
-
def self.api_key=(key)
|
21
|
-
@@api_key = key
|
22
|
-
end
|
23
|
-
def self.referer
|
24
|
-
@@referer
|
25
|
-
end
|
26
|
-
def self.referer=(referer)
|
27
|
-
@@referer = referer
|
28
|
-
end
|
29
|
-
|
30
|
-
# TODO: Pass query to parser, so it knows where it came from. Needed for search paging and useful in general.
|
31
|
-
def self.get(api, method, query, args = nil)
|
32
|
-
raise "You must assign a value to GoogleAjax.referer" unless @@referer
|
33
|
-
url = "#{API_BASE}#{api}/"
|
34
|
-
url += "#{method}?"
|
35
|
-
url += "&q=#{CGI::escape(query)}"
|
36
|
-
url += "&key=" if @@api_key
|
37
|
-
url += "&" + args.collect {|key, value| "#{key}=#{value}"}.join('&') if args && !args.empty?
|
38
|
-
data = open(url, "Referer" => @@referer).read
|
39
|
-
Parser.parse(api, method, data)
|
40
|
-
end
|
41
|
-
end
|
data/lib/google_ajax/feed.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
class GoogleAjax
|
2
|
-
class Feed
|
3
|
-
FEED_VERSION = 1.0
|
4
|
-
def self.get(method, query, args = {})
|
5
|
-
args = { :v => FEED_VERSION }.merge!(args)
|
6
|
-
GoogleAjax::get(:feed, method, query, args)
|
7
|
-
end
|
8
|
-
|
9
|
-
# will return a list of feeds that match the given query
|
10
|
-
def self.find(query, args = {})
|
11
|
-
self.get(:find, query)
|
12
|
-
end
|
13
|
-
|
14
|
-
# downloads this feed from Google's servers
|
15
|
-
# Optional: args { :num => number of entries to download(default is 4, maximum is 100) }
|
16
|
-
def self.load(query, args = {})
|
17
|
-
self.get(:load, query, args)
|
18
|
-
end
|
19
|
-
|
20
|
-
# will return the associated feed if it exists for a given url
|
21
|
-
def self.lookup(query, args = {})
|
22
|
-
self.get(:lookup, query)
|
23
|
-
end
|
24
|
-
|
25
|
-
class Entry < OpenStruct
|
26
|
-
def initialize(data)
|
27
|
-
super(data)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Feed < OpenStruct
|
32
|
-
def initialize(data)
|
33
|
-
super(data)
|
34
|
-
self.entries = entries.collect {|data| Entry.new(data)} if entries
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/google_ajax/parser.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
class GoogleAjax
|
2
|
-
class Parser
|
3
|
-
def self.parse(api, method, data)
|
4
|
-
data = JSON.parse(data)
|
5
|
-
Errors.process(data)
|
6
|
-
parser = Parser::PARSERS[api][method]
|
7
|
-
parser.process(data['responseData'])
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class FeedFind < Parser#:nodoc:
|
12
|
-
def self.process(data)
|
13
|
-
data['entries'].collect {|data| GoogleAjax::Feed::Feed.new(data)} if data
|
14
|
-
end
|
15
|
-
end
|
16
|
-
class FeedLoad < Parser#:nodoc:
|
17
|
-
def self.process(data)
|
18
|
-
GoogleAjax::Feed::Feed.new(data['feed']) if data
|
19
|
-
end
|
20
|
-
end
|
21
|
-
class FeedLookup < Parser#:nodoc:
|
22
|
-
def self.process(data)
|
23
|
-
GoogleAjax::Feed::Feed.new(data) if data
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class LanguageDetect < Parser#:nodoc
|
28
|
-
def self.process(data)
|
29
|
-
GoogleAjax::Language::Language.new(data) if data
|
30
|
-
end
|
31
|
-
end
|
32
|
-
class LanguageTranslate < Parser#:nodoc
|
33
|
-
def self.process(data)
|
34
|
-
GoogleAjax::Language::Translation.new(data) if data
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class SearchBlogs < Parser#:nodoc
|
39
|
-
def self.process(data)
|
40
|
-
GoogleAjax::Search::Results.new(data) if data
|
41
|
-
end
|
42
|
-
end
|
43
|
-
class SearchBooks < Parser#:nodoc
|
44
|
-
def self.process(data)
|
45
|
-
GoogleAjax::Search::Results.new(data) if data
|
46
|
-
end
|
47
|
-
end
|
48
|
-
class SearchImages < Parser#:nodoc
|
49
|
-
def self.process(data)
|
50
|
-
GoogleAjax::Search::Results.new(data) if data
|
51
|
-
end
|
52
|
-
end
|
53
|
-
class SearchLocal < Parser#:nodoc
|
54
|
-
def self.process(data)
|
55
|
-
GoogleAjax::Search::Results.new(data) if data
|
56
|
-
end
|
57
|
-
end
|
58
|
-
class SearchNews < Parser#:nodoc
|
59
|
-
def self.process(data)
|
60
|
-
GoogleAjax::Search::Results.new(data) if data
|
61
|
-
end
|
62
|
-
end
|
63
|
-
class SearchVideo < Parser#:nodoc
|
64
|
-
def self.process(data)
|
65
|
-
GoogleAjax::Search::Results.new(data) if data
|
66
|
-
end
|
67
|
-
end
|
68
|
-
class SearchWeb < Parser#:nodoc
|
69
|
-
def self.process(data)
|
70
|
-
GoogleAjax::Search::Results.new(data) if data
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class Parser
|
75
|
-
PARSERS = {
|
76
|
-
:feed => { :find => FeedFind, :load => FeedLoad, :lookup => FeedLookup },
|
77
|
-
:language => { :detect => LanguageDetect, :translate => LanguageTranslate, },
|
78
|
-
:search => { :blogs => SearchBlogs, :books => SearchBooks, :images => SearchImages, :local => SearchLocal, :news => SearchNews, :video => SearchVideo, :web => SearchWeb }
|
79
|
-
}
|
80
|
-
end
|
81
|
-
|
82
|
-
class Errors
|
83
|
-
def self.process(data)
|
84
|
-
status = data['responseStatus']
|
85
|
-
unless [200, 201, 202, 203, 204, 205, 206].include? status
|
86
|
-
raise StandardError.new(data['responseDetails'])
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
data/lib/google_ajax/search.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
class GoogleAjax
|
2
|
-
class Search
|
3
|
-
SEARCH_VERSION = 1.0
|
4
|
-
def self.get(method, query, args = {})
|
5
|
-
args = { :v => SEARCH_VERSION }.merge!(args)
|
6
|
-
GoogleAjax::get(:search, method, query, args)
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.blogs(query, args = {})
|
10
|
-
self.get(:blogs, query, args)
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.books(query, args = {})
|
14
|
-
self.get(:books, query, args)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.images(query, args = {})
|
18
|
-
self.get(:images, query, args)
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.local(query, latitude, longitude, args = {})
|
22
|
-
args = { :sll => "#{latitude},#{longitude}" }.merge!(args)
|
23
|
-
self.get(:local, query, args)
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.news(query, args = {})
|
27
|
-
self.get(:news, query, args)
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.video(query, args = {})
|
31
|
-
self.get(:video, query, args)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.web(query, args = {})
|
35
|
-
self.get(:web, query, args)
|
36
|
-
end
|
37
|
-
|
38
|
-
class Results < OpenStruct
|
39
|
-
def initialize(data)
|
40
|
-
super(data)
|
41
|
-
self.results = results.collect {|data| Result.new(data)}
|
42
|
-
self.cursor = Cursor.new(cursor) if self.cursor
|
43
|
-
end
|
44
|
-
|
45
|
-
def count
|
46
|
-
self.cursor.estimatedResultCount
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class Result < OpenStruct
|
51
|
-
def initialize(data)
|
52
|
-
super(data)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class Cursor < OpenStruct
|
57
|
-
def initialize(data)
|
58
|
-
super(data)
|
59
|
-
self.pages = pages.collect {|data| Page.new(data)}
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class Page < OpenStruct
|
64
|
-
def initialize(data)
|
65
|
-
super(data)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
data/lib/google_ajax/version.rb
DELETED
data/test/test_google_ajax.rb
DELETED
File without changes
|