fusion_tables 0.1.0 → 0.1.1

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/.gitignore CHANGED
@@ -16,7 +16,6 @@ tmtags
16
16
  ## PROJECT::GENERAL
17
17
  coverage
18
18
  rdoc
19
- pkg
20
19
 
21
20
  ## PROJECT::TEST
22
21
  test/test_config.yml
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Simon Tokumine
1
+ Copyright (c) 2010 Tom Verbeure, Simon Tokumine
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -1,63 +1,81 @@
1
1
  h1. fusion-tables
2
2
 
3
- This API lets you easily interact with Google Fusion Tables from your Ruby application.
3
+ This gem lets you easily interact with Google Fusion Tables from your Ruby application. Here are some "example maps and charts":http://www.tokumine.com/2010/08/10/fusion-tables-gem/.
4
+
5
+ h2. Gem Dependencies
6
+
7
+ * gdata >= 1.1.1
4
8
 
5
9
  h2. Installation
6
10
 
7
- gem install fusion-tables
11
+ bc. gem install fusion_tables
12
+
13
+ h2. To Use
14
+
15
+ bc. require 'fusion_tables'
16
+
17
+ or in Rails 2.3.x
18
+
19
+ bc. config.gem 'fusion_tables'
8
20
 
9
21
  h2. API examples
10
22
 
11
- The best place to see what's going on is in the tests, but this is a good starting point.
23
+ The best place to see examples (including uploading KML) is in the tests, but this is a good starting point.
12
24
 
13
- <pre><code>
14
- # Connect to service
25
+ <pre><code># Connect to service
15
26
  @ft = GData::Client::FusionTables.new
16
27
  @ft.clientlogin(username, password)
17
28
 
18
- # Create a new table
19
- # Configure the columns you want
20
- cols = [{:name => "friend name", :datatype => 'string' },
21
- {:name => "age", :datatype => 'number' },
22
- {:name => "meeting time", :datatype => 'datetime' },
23
- {:name => "where", :datatype => 'location' }]
24
-
25
- # Create the table
26
- @table = @ft.create_table "My upcoming meetings", cols
27
- @table.id #=> 42342 (the table's google id)
28
-
29
- # Insert data
30
- data = [{"friend name" => "Eric Wimp",
31
- "age" => 25,
32
- "meeting time" => Time.utc(2010,"aug",10,20,15,1),
33
- "where" => "29 Acacia Road, Nuttytown"]
29
+ # Browse existing tables
30
+ @ft.show_tables
31
+ # => [table_1, table_2]
34
32
 
35
- @table.insert data
36
-
37
- # Note - the insert method chunks the data array into 500 row chunks
33
+ # Getting table id suitable for using with google maps (see more below)
34
+ table_1.id #=> 42342 (the table's google id)
38
35
 
39
36
  # Count data
40
- @table.count #=> 1
37
+ table_1.count #=> 1
41
38
 
42
39
  # Select data
43
- @table.select #=> data
44
- row_ids = @table.select "ROWID"
40
+ table_1.select
41
+ #=> data
45
42
 
46
- # Update data (not working)
47
- # @table.update row_id, {:age => 26}
43
+ # Select data with conditions
44
+ table_1.select "name", "WHERE x=n"
45
+ #=> data
48
46
 
49
- # Delete data
50
- @table.delete row_id
47
+ # Select ROWIDs
48
+ row_ids = table_1.select "ROWID"
51
49
 
52
50
  # Drop tables
53
- @ft.drop @table.id # table id
54
- @ft.drop [@table1.id, @table2.id] # arrays of table ids
55
- @ft.drop /yacht/ # regex
51
+ @ft.drop table_1.id # table id
52
+ @ft.drop [table_1.id, table_2.id] # arrays of table ids
53
+ @ft.drop /yacht/ # regex on table name
54
+
55
+ # Creating a table
56
+ cols = [{:name => "friend name", :type => 'string' },
57
+ {:name => "age", :type => 'number' },
58
+ {:name => "meeting time", :type => 'datetime' },
59
+ {:name => "where", :type => 'location' }]
60
+
61
+ new_table = @ft.create_table "My upcoming meetings", cols
62
+
63
+ # Inserting rows (auto chunks every 500)
64
+ data = [{"friend name" => "Eric Wimp",
65
+ "age" => 25,
66
+ "meeting time" => Time.utc(2010,"aug",10,20,15,1),
67
+ "where" => "29 Acacia Road, Nuttytown"}]
68
+ new_table.insert data
69
+
70
+ # Delete row
71
+ new_table.delete row_id
56
72
  </code></pre>
57
73
 
58
74
  h2. Fusion Tables secret Geospatial Sauce
59
75
 
60
- Fusion Tables is a labs product from Google. You can "read more here":http://tables.googlelabs.com/, but the key thing is that it gives you *access to the google tile mill for ultra-fast generating of custom google map layers across massive datasets*
76
+ *"Geolocated Tweets example":http://tables.googlelabs.com/DataSource?snapid=73106*
77
+
78
+ Fusion Tables is a labs product from Google. You can "read more here":http://tables.googlelabs.com/, but the key thing is that it gives you *access to the google tile mill for fast generation of google map layers across large datasets*
61
79
 
62
80
  Fusion Tables supports the following geometry types:
63
81
 
@@ -65,13 +83,11 @@ Fusion Tables supports the following geometry types:
65
83
  * addresses (automatically geocodes them for you)
66
84
  * KML (point, polyline, polygon, multipolygon)
67
85
 
68
- h2. Thousands of geometries rendered in near real time, integrated with google maps v3
86
+ h2. Integrate with google maps v3
69
87
 
70
88
  Adding a fusion tables datalayer with many points/polygons to your v3 map is as simple as:
71
89
 
72
- <pre><code>
73
- layer = new google.maps.FusionTablesLayer(139529);
74
- </code></pre>
90
+ bc. layer = new google.maps.FusionTablesLayer(139529);
75
91
 
76
92
  That's it
77
93
 
@@ -95,10 +111,9 @@ You can also export your data (filtered and geocoded) to KML. As an example, her
95
111
 
96
112
  read "more here":http://code.google.com/apis/maps/documentation/javascript/overlays.html#FusionTables
97
113
 
98
- h2. A word of warning...
114
+ h2. A few words of warning...
99
115
 
100
- # Google has a recent habit of deleting projects. This is still a labs project, and may disappear at any time
101
- # The API is still very young and *will change*
116
+ # The API is still very young and *will probably change*
102
117
  # Currently you have to make a table public before you can display it on a map, unfortunately, this can only be done on the web interface. A suggested workaround is to put all your data in 1 big public table, and then query for the data you want to display based off a key/flag column
103
118
 
104
119
  h2. Note on Patches/Pull Requests
@@ -115,7 +130,7 @@ h2. Copyright
115
130
 
116
131
  Largely based on Tom Verbeure's work for MTBGuru: http://code.google.com/p/mtbguru-fusiontables/
117
132
 
118
- Copyright (c) 2010 Simon Tokumine. See LICENSE for details.
133
+ Copyright (c) 2010 Tom Verbeure, Simon Tokumine. See LICENSE for details.
119
134
 
120
135
 
121
136
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -0,0 +1,142 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Twitter Fusion Tables Mashup
4
+ # S.Tokumine 2010
5
+ #
6
+ # looks for tweets in the live stream around certain
7
+ # cities and posts them to fusion tables with KML attached
8
+ #
9
+ # Gem dependencies:
10
+ #
11
+ # tweetstream
12
+ # GeoRuby
13
+ # fusion_tables
14
+ #
15
+ # Output from running this for an evening
16
+ # http://tables.googlelabs.com/DataSource?snapid=72509
17
+ #
18
+ require 'rubygems'
19
+ require 'tweetstream'
20
+ require 'geo_ruby'
21
+ include GeoRuby
22
+ include SimpleFeatures
23
+ require 'fusion_tables'
24
+ require 'time'
25
+
26
+ class Object
27
+ def try(method, *args, &block)
28
+ send(method, *args, &block)
29
+ end
30
+ end
31
+
32
+ # Configure settings
33
+ config = YAML::load_file(File.join(File.dirname(__FILE__), 'credentials.yml'))
34
+ DEFAULT_SRID = 4328
35
+
36
+ # Twitter places
37
+ places = {
38
+ :san_francisco => [-122.75,36.8,-121.75,37.8],
39
+ :new_york => [-74,40,-73,41],
40
+ :tokyo => [139.3,35,140.3,36],
41
+ :london => [-0.54,51.2,0.46,52.2],
42
+ :madrid => [-4.2,40,-3.2,41],
43
+ :paris => [1.75,48.5,2.75, 49.5],
44
+ :beijing => [115.9,39,116.9,40],
45
+ :mumbai => [72.75,18.88,73.75,19.88],
46
+ }
47
+
48
+ # Configure fusion tables
49
+ ft = GData::Client::FusionTables.new
50
+ ft.clientlogin(config["google_username"], config["google_password"])
51
+ table_name = "twitter_fusion"
52
+ cols = [
53
+ {:name => 'screen_name', :type => 'string'},
54
+ {:name => 'avatar', :type => 'string'},
55
+ {:name => 'text', :type => 'string'},
56
+ {:name => 'created', :type => 'datetime'},
57
+ {:name => 'url', :type => 'string'},
58
+ {:name => 'location', :type => 'location'},
59
+ {:name => 'iso', :type => 'location'},
60
+ {:name => 'country_name', :type => 'location'},
61
+ {:name => 'city', :type => 'string'}
62
+ ]
63
+
64
+ # Create FT if it doesn't exist
65
+ tables = ft.show_tables
66
+ table = tables.select{|t| t.name == table_name}.first
67
+ table = ft.create_table(table_name, cols) if !table
68
+
69
+ # Configure Twitter stream client
70
+ data = []
71
+ tw = TweetStream::Client.new(config["twitter_username"],config["twitter_password"])
72
+
73
+ # configure friendly rate limit handling
74
+ tw.on_limit do |skip_count|
75
+ sleep 5
76
+ end
77
+
78
+ # start searching twitter stream and posting to FT
79
+ tw.filter(:locations => places.values.join(",")) do |tweet|
80
+ begin
81
+
82
+ country = "unknown"
83
+ iso = "unknown"
84
+ begin
85
+ country = tweet.try(:[],:place).try(:[], :country)
86
+ iso = tweet.try(:[],:place).try(:[], :country_code)
87
+ rescue
88
+ end
89
+
90
+ # Divine the tweets geometry
91
+ #
92
+ # overly complex due to
93
+ # * some US tweets have their lat/longs flipped (but not all...)
94
+ # * some geo tweets are made using a "place" envelope rather than exact lat/kng
95
+ if tweet[:geo]
96
+ if iso == 'US' && tweet[:geo][:coordinates][1] > 0
97
+ p = Point.from_x_y(tweet[:geo][:coordinates][0],tweet[:geo][:coordinates][1])
98
+ else
99
+ p = Point.from_x_y(tweet[:geo][:coordinates][1],tweet[:geo][:coordinates][0])
100
+ end
101
+ else
102
+ p = Polygon.from_coordinates(tweet[:place][:bounding_box][:coordinates]).envelope.center
103
+ end
104
+
105
+ # work out which city the tweet is from by testing with an extended bounding box
106
+ # BBox extention needed as twitter returns things outside our defined bboxes...
107
+ city = "unknown"
108
+ places.each do |key, value|
109
+ if !(p.x < value[0]-1 || p.x > value[2]+1 || p.y < value[1]-1 || p.y > value[3]+1)
110
+ city = key.to_s.gsub("_"," ")
111
+ break
112
+ end
113
+ end
114
+
115
+ # pack data
116
+ data << {
117
+ "screen_name" => tweet[:user][:screen_name],
118
+ "avatar" => tweet[:user][:profile_image_url],
119
+ "text" => tweet[:text],
120
+ "created" => Time.parse(tweet[:created_at]),
121
+ "url" => "http://twitter.com/#{tweet[:user][:screen_name]}/status/#{tweet[:id]}",
122
+ "location" => p.as_kml,
123
+ "iso" => iso,
124
+ "country_name" => country,
125
+ "city" => city
126
+ }
127
+ rescue => e
128
+ puts "ERROR: #{e.inspect}, #{e.backtrace}"
129
+ #let sleeping dogs lie...
130
+ end
131
+
132
+ # let us know how we're doing
133
+ puts "#{50-data.size}: #{city}, #{tweet.text}"
134
+
135
+ # Post to fusion tables
136
+ if data.size == 50
137
+ puts "sending data to fusion tables..."
138
+ ft_data = data
139
+ data = []
140
+ table.insert ft_data
141
+ end
142
+ end
@@ -0,0 +1,4 @@
1
+ twitter_username: your_username
2
+ twitter_password: your_password
3
+ google_username: your_username
4
+ google_password: your_password
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{fusion_tables}
8
- s.version = "0.1.0"
8
+ s.version = "0.1.1"
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{2010-08-10}
12
+ s.date = %q{2010-08-12}
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 = [
@@ -25,12 +25,16 @@ Gem::Specification.new do |s|
25
25
  "Rakefile",
26
26
  "TODO",
27
27
  "VERSION",
28
+ "examples/compare_tweets.rb",
29
+ "examples/credentials.example.yml",
28
30
  "fusion_tables.gemspec",
29
31
  "lib/fusion_tables.rb",
30
32
  "lib/fusion_tables/client/fusion_tables.rb",
31
33
  "lib/fusion_tables/data/data.rb",
32
34
  "lib/fusion_tables/data/table.rb",
33
35
  "lib/fusion_tables/ext/fusion_tables.rb",
36
+ "pkg/fusion_tables-0.1.0.gem",
37
+ "pkg/fusion_tables-0.1.1.gem",
34
38
  "test/README",
35
39
  "test/helper.rb",
36
40
  "test/test_client.rb",
@@ -47,7 +51,8 @@ Gem::Specification.new do |s|
47
51
  "test/helper.rb",
48
52
  "test/test_client.rb",
49
53
  "test/test_ext.rb",
50
- "test/test_table.rb"
54
+ "test/test_table.rb",
55
+ "examples/compare_tweets.rb"
51
56
  ]
52
57
 
53
58
  if s.respond_to? :specification_version then
@@ -114,11 +114,11 @@ module GData
114
114
  data.inject([]) do |ar,h|
115
115
  ret = {}
116
116
  h.each do |key, value|
117
- ret[key] = case get_datatype(key)
118
- when "number" then "#{value}"
119
- when "datetime" then "'#{value.strftime("%m-%d-%Y")}'"
120
- else "'#{value.gsub(/\\/, '\&\&').gsub(/'/, "''")}'"
121
- end
117
+ ret["'#{key.to_s}'"] = case get_datatype(key)
118
+ when "number" then "#{value}"
119
+ when "datetime" then "'#{value.strftime("%m-%d-%Y")}'"
120
+ else "'#{value.gsub(/\\/, '\&\&').gsub(/'/, "''")}'"
121
+ end
122
122
  end
123
123
  ar << ret
124
124
  ar
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fusion_tables
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Simon Tokumine
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-08-10 00:00:00 +01:00
19
+ date: 2010-08-12 00:00:00 +01:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -67,12 +67,16 @@ files:
67
67
  - Rakefile
68
68
  - TODO
69
69
  - VERSION
70
+ - examples/compare_tweets.rb
71
+ - examples/credentials.example.yml
70
72
  - fusion_tables.gemspec
71
73
  - lib/fusion_tables.rb
72
74
  - lib/fusion_tables/client/fusion_tables.rb
73
75
  - lib/fusion_tables/data/data.rb
74
76
  - lib/fusion_tables/data/table.rb
75
77
  - lib/fusion_tables/ext/fusion_tables.rb
78
+ - pkg/fusion_tables-0.1.0.gem
79
+ - pkg/fusion_tables-0.1.1.gem
76
80
  - test/README
77
81
  - test/helper.rb
78
82
  - test/test_client.rb
@@ -118,3 +122,4 @@ test_files:
118
122
  - test/test_client.rb
119
123
  - test/test_ext.rb
120
124
  - test/test_table.rb
125
+ - examples/compare_tweets.rb