fusion_tables 0.2.4 → 0.3.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/CHANGELOG +8 -0
- data/README.md +24 -15
- data/{TODO → TODO.md} +9 -2
- data/VERSION +1 -1
- data/fusion_tables.gemspec +27 -37
- data/lib/fusion_tables/client/fusion_tables.rb +8 -9
- data/lib/fusion_tables/data/table.rb +6 -10
- data/lib/fusion_tables/ext/fusion_tables.rb +8 -2
- data/test/test_sql.rb +80 -0
- metadata +9 -34
- data/.gitignore +0 -26
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
fusion-tables
|
2
2
|
==============
|
3
3
|
|
4
|
-
This gem lets you easily interact with [Google Fusion Tables](http://www.google.com/fusiontables/Home) from your Ruby application.
|
4
|
+
This gem lets you easily interact with [Google Fusion Tables](http://www.google.com/fusiontables/Home) from your Ruby application. There is a plain SQL interface, or an object orientated interface available.
|
5
5
|
|
6
6
|
Demo and examples
|
7
7
|
------------------
|
8
8
|
|
9
|
-
* Twitter [demo](http://tables.googlelabs.com/DataSource?snapid=73106) / [code](http://github.com/tokumine/
|
10
|
-
|
11
|
-
* [
|
9
|
+
* Twitter [demo](http://tables.googlelabs.com/DataSource?snapid=73106) / [code](http://github.com/tokumine/fusion_tables/blob/master/examples/compare_tweets.rb) /
|
10
|
+
[blog](http://www.tokumine.com/2010/08/10/fusion-tables-gem/)
|
11
|
+
* Boris bike [demo](http://tables.googlelabs.com/DataSource?snapid=78314) / [code](http://github.com/tokumine/fusion_tables/blob/master/examples/boris_bikes.rb)
|
12
|
+
* [Tests](http://github.com/tokumine/fusion_tables/tree/master/test/)
|
13
|
+
|
12
14
|
|
13
15
|
Installation
|
14
16
|
-------------
|
@@ -31,10 +33,21 @@ Usage
|
|
31
33
|
``` ruby
|
32
34
|
require 'fusion_tables'
|
33
35
|
|
36
|
+
|
34
37
|
# Connect to service
|
35
38
|
@ft = GData::Client::FusionTables.new
|
36
39
|
@ft.clientlogin(username, password)
|
37
40
|
|
41
|
+
|
42
|
+
# 1. Simple SQL interface
|
43
|
+
# =========================
|
44
|
+
@ft.execute "SHOW TABLES"
|
45
|
+
@ft.execute "INSERT INTO #{my_table_id} (name, geo) VALUES ('tokyo', '35.6894 139.6917');"
|
46
|
+
@ft.execute "SELECT count() FROM #{my_table_id};"
|
47
|
+
|
48
|
+
|
49
|
+
# 2. basic ORM interface
|
50
|
+
# ========================
|
38
51
|
# Browse existing tables
|
39
52
|
@ft.show_tables
|
40
53
|
# => [table_1, table_2]
|
@@ -76,21 +89,17 @@ data = [{"friend name" => "Eric Wimp",
|
|
76
89
|
"where" => "29 Acacia Road, Nuttytown"}]
|
77
90
|
new_table.insert data
|
78
91
|
|
79
|
-
#
|
80
|
-
new_table.
|
81
|
-
```
|
92
|
+
# Currently FT API only supports single row UPDATE.
|
93
|
+
new_table.update 1, [{"friend name" => "Bananaman"}]
|
82
94
|
|
83
|
-
|
95
|
+
# Delete row
|
96
|
+
new_table.delete 1
|
84
97
|
|
85
|
-
|
86
|
-
|
87
|
-
data = [{"friend name" => "Eric Wimp",
|
88
|
-
"age" => 25,
|
89
|
-
"meeting time" => Time.utc(2010,"aug",10,20,15,1),
|
90
|
-
"where" => "29 Acacia Road, Nuttytown"}]
|
91
|
-
new_table.update row_id, data
|
98
|
+
# Delete all rows
|
99
|
+
new_table.truncate!
|
92
100
|
```
|
93
101
|
|
102
|
+
|
94
103
|
Known Issues
|
95
104
|
-------------
|
96
105
|
|
data/{TODO → TODO.md}
RENAMED
@@ -1,6 +1,13 @@
|
|
1
|
-
|
1
|
+
Gem
|
2
|
+
====
|
3
|
+
* YARD docs
|
2
4
|
|
3
|
-
|
5
|
+
|
6
|
+
|
7
|
+
API wishlist
|
8
|
+
=============
|
9
|
+
* Bulk UPDATE
|
10
|
+
* response format in json/xml
|
4
11
|
* "create table" should return name
|
5
12
|
* describe table should include name
|
6
13
|
* multiple batch statements for all actions (only insert now). Need on all other commands. Better SQL.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/fusion_tables.gemspec
CHANGED
@@ -1,60 +1,50 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{fusion_tables}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Simon Tokumine", "Tom Verbeure"]
|
12
|
-
s.date = %q{2011-06-
|
12
|
+
s.date = %q{2011-06-05}
|
13
13
|
s.description = %q{A simple Google Fusion Tables API wrapper. Supports bulk inserts and most API functions}
|
14
14
|
s.email = %q{simon@tinypla.net}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
|
18
|
-
"TODO"
|
17
|
+
"README.md"
|
19
18
|
]
|
20
19
|
s.files = [
|
21
20
|
".document",
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
21
|
+
"CHANGELOG",
|
22
|
+
"LICENSE",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"TODO.md",
|
26
|
+
"VERSION",
|
27
|
+
"examples/boris_bikes.rb",
|
28
|
+
"examples/compare_tweets.rb",
|
29
|
+
"examples/credentials.example.yml",
|
30
|
+
"fusion_tables.gemspec",
|
31
|
+
"lib/fusion_tables.rb",
|
32
|
+
"lib/fusion_tables/client/fusion_tables.rb",
|
33
|
+
"lib/fusion_tables/data/data.rb",
|
34
|
+
"lib/fusion_tables/data/table.rb",
|
35
|
+
"lib/fusion_tables/ext/fusion_tables.rb",
|
36
|
+
"test/README",
|
37
|
+
"test/helper.rb",
|
38
|
+
"test/test_client.rb",
|
39
|
+
"test/test_config.yml.sample",
|
40
|
+
"test/test_ext.rb",
|
41
|
+
"test/test_sql.rb",
|
42
|
+
"test/test_table.rb"
|
44
43
|
]
|
45
44
|
s.homepage = %q{http://github.com/tokumine/fusion_tables}
|
46
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
47
45
|
s.require_paths = ["lib"]
|
48
|
-
s.rubygems_version = %q{1.
|
46
|
+
s.rubygems_version = %q{1.6.2}
|
49
47
|
s.summary = %q{Google Fusion Tables API wrapper}
|
50
|
-
s.test_files = [
|
51
|
-
"test/helper.rb",
|
52
|
-
"test/test_client.rb",
|
53
|
-
"test/test_ext.rb",
|
54
|
-
"test/test_table.rb",
|
55
|
-
"examples/boris_bikes.rb",
|
56
|
-
"examples/compare_tweets.rb"
|
57
|
-
]
|
58
48
|
|
59
49
|
if s.respond_to? :specification_version then
|
60
50
|
s.specification_version = 3
|
@@ -20,28 +20,27 @@ module GData
|
|
20
20
|
DATATYPES = %w(number string location datetime)
|
21
21
|
|
22
22
|
def initialize(options = {})
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
options[:clientlogin_service] ||= 'fusiontables'
|
24
|
+
options[:headers] = { 'Content-Type' => 'application/x-www-form-urlencoded' }
|
25
|
+
super(options)
|
26
26
|
end
|
27
27
|
|
28
28
|
def sql_encode(sql)
|
29
|
-
|
29
|
+
"sql=" + CGI::escape(sql)
|
30
30
|
end
|
31
31
|
|
32
32
|
def sql_get(sql)
|
33
|
-
|
33
|
+
resp = self.get(SERVICE_URL + "?" + sql_encode(sql))
|
34
34
|
end
|
35
35
|
|
36
36
|
def sql_post(sql)
|
37
|
-
|
37
|
+
resp = self.post(SERVICE_URL, sql_encode(sql))
|
38
38
|
end
|
39
39
|
|
40
40
|
def sql_put(sql)
|
41
|
-
|
41
|
+
resp = self.put(SERVICE_URL, sql_encode(sql))
|
42
42
|
end
|
43
|
-
|
44
|
-
|
43
|
+
|
45
44
|
# Overrides auth_handler= so if the authentication changes,
|
46
45
|
# the session cookie is cleared.
|
47
46
|
def auth_handler=(handler)
|
@@ -30,11 +30,10 @@ module GData
|
|
30
30
|
@name = options[:name]
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
33
|
# Sets up data types from google
|
35
34
|
#
|
36
35
|
def describe
|
37
|
-
|
36
|
+
@client.execute "DESCRIBE #{@id}"
|
38
37
|
end
|
39
38
|
|
40
39
|
# Runs select and returns data obj
|
@@ -46,8 +45,7 @@ module GData
|
|
46
45
|
# use columns=ROWID to select row ids
|
47
46
|
#
|
48
47
|
def select columns="*", conditions=nil
|
49
|
-
|
50
|
-
GData::Client::FusionTables::Data.parse(@client.sql_get(sql)).body
|
48
|
+
@client.execute "SELECT #{columns} FROM #{@id} #{conditions}"
|
51
49
|
end
|
52
50
|
|
53
51
|
# Returns a count of rows. SQL conditions optional
|
@@ -92,19 +90,17 @@ module GData
|
|
92
90
|
def update row_id, data
|
93
91
|
data = encode([data]).first
|
94
92
|
data = data.to_a.map{|x| x.join("=")}.join(", ")
|
95
|
-
|
96
|
-
GData::Client::FusionTables::Data.parse(@client.sql_post(sql)).body
|
93
|
+
@client.execute "UPDATE #{@id} SET #{data} WHERE ROWID = '#{row_id}'"
|
97
94
|
end
|
98
95
|
|
99
96
|
# delete row
|
100
97
|
def delete row_id
|
101
|
-
|
102
|
-
GData::Client::FusionTables::Data.parse(@client.sql_post(sql)).body
|
98
|
+
@client.execute "DELETE FROM #{@id} WHERE rowid='#{row_id}'"
|
103
99
|
end
|
104
100
|
|
105
101
|
# delete all rows
|
106
102
|
def truncate!
|
107
|
-
|
103
|
+
@client.execute "DELETE FROM #{@id}"
|
108
104
|
end
|
109
105
|
|
110
106
|
def get_headers
|
@@ -130,7 +126,7 @@ module GData
|
|
130
126
|
ar
|
131
127
|
end
|
132
128
|
end
|
133
|
-
|
129
|
+
|
134
130
|
#
|
135
131
|
# Returns datatype of given column name
|
136
132
|
#
|
@@ -15,16 +15,22 @@
|
|
15
15
|
module GData
|
16
16
|
module Client
|
17
17
|
class FusionTables < Base
|
18
|
+
|
19
|
+
# Helper method to run FT SQL and return FT data object
|
20
|
+
def execute(sql)
|
21
|
+
http_req = sql.upcase.match(/^(DESCRIBE|SHOW|SELECT)/) ? :sql_get : :sql_post
|
22
|
+
GData::Client::FusionTables::Data.parse(self.send(http_req, sql)).body
|
23
|
+
end
|
18
24
|
|
19
25
|
# Show a list of fusion tables
|
20
26
|
def show_tables
|
21
|
-
data =
|
27
|
+
data = self.execute "SHOW TABLES"
|
28
|
+
|
22
29
|
data.inject([]) do |x, row|
|
23
30
|
x << GData::Client::FusionTables::Table.new(self, row)
|
24
31
|
x
|
25
32
|
end
|
26
33
|
end
|
27
|
-
|
28
34
|
|
29
35
|
# Create a new table. Return the corresponding table
|
30
36
|
#
|
data/test/test_sql.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestTable < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "testing plain SQL" do
|
6
|
+
setup do
|
7
|
+
init_config
|
8
|
+
@ft = GData::Client::FusionTables.new
|
9
|
+
@ft.clientlogin(username, password)
|
10
|
+
@table = @ft.create_table "test", [{:name => 'firstname', :type => 'string'},
|
11
|
+
{:name => 'phone', :type => 'number'},
|
12
|
+
{:name => 'dob', :type => 'datetime'},
|
13
|
+
{:name => 'house', :type => 'location'}]
|
14
|
+
end
|
15
|
+
|
16
|
+
should "be able to SHOW TABLES" do
|
17
|
+
ret = @ft.execute "SHOW TABLES"
|
18
|
+
assert !ret.empty?
|
19
|
+
assert_equal Array, ret.class
|
20
|
+
end
|
21
|
+
|
22
|
+
should "be able to DESCRIBE a table" do
|
23
|
+
ret = @ft.execute("DESCRIBE #{@table.id}")
|
24
|
+
expected = [{:column_id=>"col0", :name=>"firstname", :type=>"string"},
|
25
|
+
{:column_id=>"col1", :name=>"phone", :type=>"number"},
|
26
|
+
{:column_id=>"col2", :name=>"dob", :type=>"datetime"},
|
27
|
+
{:column_id=>"col3", :name=>"house", :type=>"location"}]
|
28
|
+
assert_equal expected, ret
|
29
|
+
end
|
30
|
+
|
31
|
+
should "be able to INSERT a row" do
|
32
|
+
ret = @ft.execute "INSERT INTO #{@table.id} (firstname) VALUES ('eric');"
|
33
|
+
assert_equal 1, ret.first[:rowid].to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
should "be able to SELECT a row" do
|
37
|
+
@ft.execute "INSERT INTO #{@table.id} (firstname) VALUES ('eric');"
|
38
|
+
ret = @ft.execute "SELECT ROWID, firstname FROM #{@table.id}"
|
39
|
+
assert_equal [{:rowid=>"1", :firstname=>"eric"}], ret
|
40
|
+
end
|
41
|
+
|
42
|
+
should "be able to UPDATE a row" do
|
43
|
+
@ft.execute "INSERT INTO #{@table.id} (firstname) VALUES ('eric');"
|
44
|
+
|
45
|
+
ret = @ft.execute "SELECT ROWID, firstname FROM #{@table.id}"
|
46
|
+
assert_equal [{:rowid=>"1", :firstname=>"eric"}], ret
|
47
|
+
|
48
|
+
ret = @ft.execute "UPDATE #{@table.id} SET firstname='simon' WHERE ROWID = '#{ret.first[:rowid]}'"
|
49
|
+
ret = @ft.execute "SELECT ROWID, firstname FROM #{@table.id}"
|
50
|
+
assert_equal [{:rowid=>"1", :firstname=>"simon"}], ret
|
51
|
+
end
|
52
|
+
|
53
|
+
should "be able to DELETE a row" do
|
54
|
+
@ft.execute "INSERT INTO #{@table.id} (firstname) VALUES ('eric');"
|
55
|
+
@ft.execute "INSERT INTO #{@table.id} (firstname) VALUES ('eric');"
|
56
|
+
|
57
|
+
ret = @ft.execute "SELECT ROWID FROM #{@table.id};"
|
58
|
+
@ft.execute "DELETE FROM #{@table.id} WHERE ROWID = '#{ret.first[:rowid]}';"
|
59
|
+
|
60
|
+
ret = @ft.execute "SELECT count() FROM #{@table.id};"
|
61
|
+
|
62
|
+
assert_equal 1, ret.first[:"count()"].to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
# should "be able to query geographic data" do
|
66
|
+
# @table = @ft.create_table "test", [{:name => 'name', :type => 'string'},
|
67
|
+
# {:name => 'geo', :type => 'location'}]
|
68
|
+
#
|
69
|
+
# @ft.execute "INSERT INTO #{@table.id} (name, geo) VALUES ('tokyo', '35.6894 139.6917');
|
70
|
+
# INSERT INTO #{@table.id} (name, geo) VALUES ('osaka', '34.6937 135.5021');
|
71
|
+
# INSERT INTO #{@table.id} (name, geo) VALUES ('fukuoka', '33.5903 130.4017');
|
72
|
+
# INSERT INTO #{@table.id} (name, geo) VALUES ('kyoto', '35.0116 135.7680');
|
73
|
+
# INSERT INTO #{@table.id} (name, geo) VALUES ('nagoya', '35.1814 136.9063');"
|
74
|
+
#
|
75
|
+
# # get cities nearest to Nara
|
76
|
+
# res = @ft.execute "SELECT * FROM #{@table.id} ORDER BY ST_DISTANCE(geo, LATLNG(35.6894,139.6917)) LIMIT 10"
|
77
|
+
# puts res.inspect
|
78
|
+
# end
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fusion_tables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 31
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 2
|
9
|
-
- 4
|
10
|
-
version: 0.2.4
|
5
|
+
version: 0.3.0
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Simon Tokumine
|
@@ -16,7 +11,7 @@ autorequire:
|
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
13
|
|
19
|
-
date: 2011-06-
|
14
|
+
date: 2011-06-05 00:00:00 +01:00
|
20
15
|
default_executable:
|
21
16
|
dependencies:
|
22
17
|
- !ruby/object:Gem::Dependency
|
@@ -27,9 +22,6 @@ dependencies:
|
|
27
22
|
requirements:
|
28
23
|
- - ">="
|
29
24
|
- !ruby/object:Gem::Version
|
30
|
-
hash: 3
|
31
|
-
segments:
|
32
|
-
- 0
|
33
25
|
version: "0"
|
34
26
|
type: :development
|
35
27
|
version_requirements: *id001
|
@@ -41,11 +33,6 @@ dependencies:
|
|
41
33
|
requirements:
|
42
34
|
- - ">="
|
43
35
|
- !ruby/object:Gem::Version
|
44
|
-
hash: 23
|
45
|
-
segments:
|
46
|
-
- 1
|
47
|
-
- 1
|
48
|
-
- 2
|
49
36
|
version: 1.1.2
|
50
37
|
type: :runtime
|
51
38
|
version_requirements: *id002
|
@@ -58,15 +45,13 @@ extensions: []
|
|
58
45
|
extra_rdoc_files:
|
59
46
|
- LICENSE
|
60
47
|
- README.md
|
61
|
-
- TODO
|
62
48
|
files:
|
63
49
|
- .document
|
64
|
-
- .gitignore
|
65
50
|
- CHANGELOG
|
66
51
|
- LICENSE
|
67
52
|
- README.md
|
68
53
|
- Rakefile
|
69
|
-
- TODO
|
54
|
+
- TODO.md
|
70
55
|
- VERSION
|
71
56
|
- examples/boris_bikes.rb
|
72
57
|
- examples/compare_tweets.rb
|
@@ -82,14 +67,15 @@ files:
|
|
82
67
|
- test/test_client.rb
|
83
68
|
- test/test_config.yml.sample
|
84
69
|
- test/test_ext.rb
|
70
|
+
- test/test_sql.rb
|
85
71
|
- test/test_table.rb
|
86
72
|
has_rdoc: true
|
87
73
|
homepage: http://github.com/tokumine/fusion_tables
|
88
74
|
licenses: []
|
89
75
|
|
90
76
|
post_install_message:
|
91
|
-
rdoc_options:
|
92
|
-
|
77
|
+
rdoc_options: []
|
78
|
+
|
93
79
|
require_paths:
|
94
80
|
- lib
|
95
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -97,30 +83,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
83
|
requirements:
|
98
84
|
- - ">="
|
99
85
|
- !ruby/object:Gem::Version
|
100
|
-
hash: 3
|
101
|
-
segments:
|
102
|
-
- 0
|
103
86
|
version: "0"
|
104
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
88
|
none: false
|
106
89
|
requirements:
|
107
90
|
- - ">="
|
108
91
|
- !ruby/object:Gem::Version
|
109
|
-
hash: 3
|
110
|
-
segments:
|
111
|
-
- 0
|
112
92
|
version: "0"
|
113
93
|
requirements: []
|
114
94
|
|
115
95
|
rubyforge_project:
|
116
|
-
rubygems_version: 1.
|
96
|
+
rubygems_version: 1.6.2
|
117
97
|
signing_key:
|
118
98
|
specification_version: 3
|
119
99
|
summary: Google Fusion Tables API wrapper
|
120
|
-
test_files:
|
121
|
-
|
122
|
-
- test/test_client.rb
|
123
|
-
- test/test_ext.rb
|
124
|
-
- test/test_table.rb
|
125
|
-
- examples/boris_bikes.rb
|
126
|
-
- examples/compare_tweets.rb
|
100
|
+
test_files: []
|
101
|
+
|
data/.gitignore
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
## MAC OS
|
2
|
-
.DS_Store
|
3
|
-
|
4
|
-
## TEXTMATE
|
5
|
-
*.tmproj
|
6
|
-
tmtags
|
7
|
-
|
8
|
-
## EMACS
|
9
|
-
*~
|
10
|
-
\#*
|
11
|
-
.\#*
|
12
|
-
|
13
|
-
## VIM
|
14
|
-
*.swp
|
15
|
-
|
16
|
-
## PROJECT::GENERAL
|
17
|
-
coverage
|
18
|
-
rdoc
|
19
|
-
examples/credentials.yml
|
20
|
-
|
21
|
-
## PROJECT::TEST
|
22
|
-
test/test_config.yml
|
23
|
-
|
24
|
-
|
25
|
-
## PROJECT::SPECIFIC
|
26
|
-
|