geoiq 0.0.3

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.
@@ -0,0 +1,53 @@
1
+ require 'httparty'
2
+ require 'pathname'
3
+ require 'uri'
4
+ require 'json'
5
+ require 'base64'
6
+
7
+ dir = Pathname(__FILE__).dirname.expand_path
8
+ require dir+"geoiq/auth"
9
+
10
+ require dir+"geoiq/base_model"
11
+ require dir+"geoiq/errors"
12
+ require dir+"geoiq/search"
13
+ require dir+"geoiq/map"
14
+ require dir+"geoiq/dataset"
15
+ require dir+"geoiq/analysis"
16
+
17
+
18
+ class Geoiq
19
+ attr_reader :request, :auth, :api_methods
20
+
21
+ def initialize(url, username, password, options = {})
22
+ # @api_methods = %w(clients contacts projects tasks people)
23
+ @api_methods = %w(dataset search map)
24
+
25
+ @auth = Auth.new(url, username, password)
26
+ # raise InvalidCredentials unless credentials.valid?
27
+ end
28
+
29
+ def dataset
30
+ @dataset||= Geoiq::Dataset.new(auth)
31
+ end
32
+
33
+ def search(query, options={}, format='json')
34
+ Geoiq::Search.new(auth).search(query, options, format)
35
+ end
36
+
37
+ def map(options={})
38
+ Geoiq::Map.new(auth, options)
39
+ end
40
+
41
+ def analysis(options={})
42
+ Geoiq::Analysis.new(auth, options)
43
+ end
44
+
45
+
46
+ class << self
47
+ def client(url, username, password, options = {})
48
+ new(url, username, password, options)
49
+ end
50
+ end
51
+
52
+ end
53
+
@@ -0,0 +1,21 @@
1
+ class Geoiq
2
+ class Analysis < BaseModel
3
+
4
+
5
+ def initialize(auth, options={})
6
+ super
7
+ end
8
+
9
+ def create(options={})
10
+ response = request(:post, "/analysis.json", {:query => options})
11
+ id = response.headers["location"].match(/(\d+)\.json/)[1].to_i
12
+
13
+ return Geoiq::Dataset.new(auth).find(id)
14
+ end
15
+
16
+
17
+
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,21 @@
1
+ class Geoiq
2
+ class Auth
3
+ attr_accessor :url, :username, :password, :ssl
4
+
5
+ def initialize(url, username, password)
6
+ @url, @username, @password = url, username, password
7
+ end
8
+
9
+ def valid?
10
+ !url.nil? && !username.nil? && !password.nil?
11
+ end
12
+
13
+ def basic_auth
14
+ Base64.encode64("#{username}:#{password}").delete("\r\n")
15
+ end
16
+
17
+ def host
18
+ @url
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ class Geoiq
2
+ class BaseModel
3
+ attr_reader :auth, :json
4
+
5
+ def initialize(auth, options={})
6
+ @auth = auth
7
+ end
8
+
9
+
10
+ class << self
11
+ def api_methods(methods)
12
+ class_eval <<-END
13
+ def api_methods
14
+ #{methods.inspect}
15
+ end
16
+ END
17
+ end
18
+
19
+ def crud
20
+ %w(find create update delete)
21
+ end
22
+
23
+
24
+ end
25
+
26
+ protected
27
+
28
+ # parse in json and create a new model
29
+ def self.parse(response, auth, options=nil)
30
+ model = self.new(auth, options)
31
+ json = JSON.parse(response.body)
32
+ model.json = json #stuff the json in there for good measure
33
+ model.attributes.each do |a|
34
+ model.send("#{a}=", json[a])
35
+ end
36
+
37
+ model
38
+
39
+ end
40
+
41
+ def request(method, path, options = {})
42
+
43
+ response = HTTParty.send(method, "#{auth.url}#{path}", :query => options[:query], :body => options[:body], :headers => {"Accept" => "application/xml", "Content-Type" => "application/xml; charset=utf-8", "Authorization" => "Basic #{auth.basic_auth}"}.update(options[:headers] || {}), :format => :plain)
44
+ case response.code
45
+ when 503
46
+ p 503 #TODO, raise errors
47
+ else
48
+ response
49
+ end
50
+ end
51
+
52
+
53
+ def requires_geoiq_id
54
+ raise NoGeoiqIDFoundError unless self.geoiq_id
55
+ end
56
+
57
+ end
58
+ end
59
+
@@ -0,0 +1,18 @@
1
+ module Geoiq
2
+
3
+ class Client
4
+ include HTTParty
5
+ default_timeout 240
6
+
7
+ def initialize(url, username=nil, password=nil)
8
+ @username = username
9
+ @url = url
10
+ self.class.base_uri(url)
11
+ @auth = {:username => username, :password => password}
12
+ end
13
+
14
+
15
+ end
16
+
17
+ end
18
+
@@ -0,0 +1,123 @@
1
+ class Geoiq
2
+ class Dataset < BaseModel
3
+ api_methods crud + %w(features csv_upload)
4
+
5
+ attr_accessor :geoiq_id, :title, :description, :tags, :published, :data_type, :feature_count, :link, :json
6
+
7
+ def attributes
8
+ %w{title description tags published data_type feature_count link}
9
+ end
10
+
11
+ def initialize(auth, options = {})
12
+ self.geoiq_id = options.delete(:geoiq_id) if options.include?(:geoiq_id)
13
+ self.title = options[:title] || "Untitled"
14
+ self.description = options[:description] || ""
15
+ self.tags = options[:tags] || ""
16
+ super
17
+ end
18
+
19
+ # datasets.find(123)
20
+ def find(id, options={})
21
+ options = {:include_geometry=>0}
22
+ response = request(:get, "/datasets/#{id}.json", {:query => options})
23
+ dataset = Geoiq::Dataset.parse(response, auth, {:geoiq_id => id})
24
+ dataset
25
+ end
26
+
27
+ def update(options)
28
+ requires_geoiq_id
29
+ self.title ||= options[:title]
30
+ self.description ||= options[:description]
31
+ self.tags ||= options[:tags]
32
+ self.attributes ||= options[:attributes]
33
+ overlay = {:overlay => options}
34
+ response = request(:put, "/datasets/#{self.geoiq_id}.json", {:query => overlay})
35
+ return true if response["status"].to_i == 200 || response["status"].to_i == 201
36
+ end
37
+
38
+ def delete
39
+ requires_geoiq_id
40
+ response = request(:delete, "/datasets/#{self.geoiq_id}.json")
41
+ return true if response["status"].to_i == 204
42
+ end
43
+
44
+
45
+ def features(options={})
46
+ requires_geoiq_id
47
+
48
+ response = request(:get, "/datasets/#{self.geoiq_id}/features.json", {:query => options})
49
+ features = JSON.parse(response.body)
50
+
51
+
52
+ end
53
+
54
+ def csv_upload(filename, options={})
55
+ type = "text/csv"
56
+
57
+ content = File.read(filename)
58
+ response = request(:post, "/datasets.json",
59
+ {:body => content,
60
+ :headers =>{ "Content-Type" => "#{type}"},
61
+ :query => options})
62
+
63
+ id = response.headers["location"].match(/(\d+)\.json/)[1].to_i
64
+
65
+ return find(id)
66
+ end
67
+
68
+ def shp_upload(shp_file, dbf_file, shx_file)
69
+
70
+ body = shp_upload_body(shp_file, dbf_file, shx_file)
71
+ response = request(:post, "/datasets.json",
72
+ {:body => body,
73
+ :headers =>{ "Content-Type" => "multipart/form-data, boundary=89d6e3836995"}
74
+ })
75
+ id = response.headers["location"].match(/(\d+)\.json/)[1].to_i
76
+
77
+ return find(id)
78
+
79
+ end
80
+
81
+ # Create a new dataset by passing in a url, and optional type
82
+ # type = csv,kml,rss, wms, tile
83
+ def url_upload(url, options={})
84
+ query = {:url => url}.merge(options)
85
+ response = request(:post, "/datasets.json", {:query => query})
86
+ id = response.headers["location"].match(/(\d+)\.json/)[1].to_i
87
+
88
+ return find(id)
89
+ end
90
+
91
+ private
92
+
93
+ def shp_upload_body(shp_file, dbf_file, shx_file)
94
+ boundary = "89d6e3836995"
95
+
96
+ body = []
97
+
98
+ body << "--#{boundary}\r\n"
99
+ body << "Content-Disposition: form-data; name=\"dataset[shp]\"; filename=\"#{File.basename(shp_file)}\"\r\n"
100
+ body << "Content-Type: application/octet-stream\r\n"
101
+ body << "\r\n"
102
+ body << File.read(shp_file)
103
+
104
+ body << "\r\n--#{boundary}\r\n"
105
+ body << "Content-Disposition: form-data; name=\"dataset[dbf]\"; filename=\"#{File.basename(dbf_file)}\"\r\n"
106
+ body << "Content-Type: application/octet-stream\r\n"
107
+ body << "\r\n"
108
+ body << File.read(dbf_file)
109
+
110
+ body << "\r\n--#{boundary}\r\n"
111
+ body << "Content-Disposition: form-data; name=\"dataset[shx]\"; filename=\"#{File.basename(shx_file)}\"\r\n"
112
+ body << "Content-Type: application/octet-stream\r\n"
113
+ body << "\r\n"
114
+ body << File.read(shx_file)
115
+
116
+ body << "\r\n--#{boundary}--\r\n"
117
+
118
+ body.join
119
+ end
120
+
121
+ end
122
+ end
123
+
@@ -0,0 +1,4 @@
1
+ class Geoiq
2
+ class InvalidCredentials < StandardError; end
3
+ class NoGeoiqIDFoundError < StandardError; end
4
+ end
@@ -0,0 +1,63 @@
1
+ class Geoiq
2
+ class Map < BaseModel
3
+ api_methods crud + %w(add_layer)
4
+
5
+ attr_accessor :geoiq_id, :title, :description, :tags, :basemap, :published, :extent, :layers, :json
6
+
7
+ def attributes
8
+ %w{title description tags basemap extent layers}
9
+ end
10
+
11
+ def initialize(auth, options={})
12
+ self.geoiq_id = options.delete(:geoiq_id) if options.include?(:geoiq_id)
13
+ self.title = options[:title] || "Untitled Map"
14
+ self.tags = (options[:tags] || []).join(",")
15
+ self.extent = options[:extent] || [-180,-90,180,90]
16
+ self.basemap = options[:basemap] || "Acetate"
17
+ self.layers = options[:layers] || []
18
+ super
19
+ end
20
+
21
+ def find(id, options={})
22
+ response = request(:get, "/maps/#{id}.json", {:query => options})
23
+ map = Geoiq::Map.parse(response, auth, {:geoiq_id => id})
24
+ map
25
+ end
26
+
27
+ def create(options={})
28
+ self.attributes.each do |a|
29
+ options.merge!({a => self.send(a)})
30
+ end
31
+
32
+ response = request(:post, "/maps.json", {:query => options})
33
+
34
+ id = response.headers["location"].match(/(\d+)\.json/)[1].to_i
35
+
36
+ return find(id)
37
+ end
38
+
39
+ def update(options={})
40
+ requires_geoiq_id
41
+ response = request(:put, "/maps/#{self.geoiq_id}.json", {:query => options})
42
+ return true if response["status"].to_i == 200 || response["status"].to_i == 201
43
+ end
44
+
45
+ def delete
46
+ requires_geoiq_id
47
+ response = request(:delete, "/maps/#{self.geoiq_id}.json")
48
+ return true if response["status"].to_i == 204
49
+ end
50
+
51
+ # layers are an array of ids of datasets to add
52
+ def add_layer(layer)
53
+ requires_geoiq_id
54
+ options = {:source => "finder:#{layer}"}
55
+ response = request(:post, "/maps/#{self.geoiq_id}/layers.json", {:query => options})
56
+ layer_index = response.headers["location"].match(/(\d+)\.json/)[1].to_i
57
+ return layer_index if response["status"].to_i == 201
58
+ end
59
+
60
+
61
+
62
+ end
63
+ end
@@ -0,0 +1,26 @@
1
+ class Geoiq
2
+ class Search
3
+ attr_reader :auth
4
+ def initialize(auth, options={})
5
+ @auth = auth
6
+ end
7
+
8
+ #format json/atom/kml
9
+ def search(query, options={}, format='json')
10
+ params = {:query => query}.merge(options)
11
+ response = request(:get, "/search.#{format}", {:query => params })
12
+ if format == 'json'
13
+ return results = JSON.parse(response.body)
14
+ else
15
+ return response.body
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def request(method, path, options = {})
22
+ response = HTTParty.send(method, "#{auth.url}#{path}", :query => options[:query], :body => options[:body], :headers => {"Accept" => "application/xml", "Content-Type" => "application/xml; charset=utf-8", "Authorization" => "Basic #{auth.basic_auth}"}.update(options[:headers] || {}), :format => :plain)
23
+ end
24
+
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geoiq
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tim Waters, John Hinnegan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: &2151938260 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.7.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2151938260
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ requirement: &2151936400 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.1.9
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2151936400
36
+ - !ruby/object:Gem::Dependency
37
+ name: shoulda
38
+ requirement: &2151935760 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2151935760
47
+ - !ruby/object:Gem::Dependency
48
+ name: fakeweb
49
+ requirement: &2151934960 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2151934960
58
+ - !ruby/object:Gem::Dependency
59
+ name: geo_ruby
60
+ requirement: &2151933720 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2151933720
69
+ description:
70
+ email: tim.waters@geoiq.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/geoiq/analysis.rb
76
+ - lib/geoiq/auth.rb
77
+ - lib/geoiq/base_model.rb
78
+ - lib/geoiq/client.rb
79
+ - lib/geoiq/dataset.rb
80
+ - lib/geoiq/errors.rb
81
+ - lib/geoiq/map.rb
82
+ - lib/geoiq/search.rb
83
+ - lib/geoiq.rb
84
+ homepage: http://github.com/fortiusone/geoiq_gem
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.10
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: API Wrapper around Geocommons website and the GeoIQ applications
108
+ test_files: []