geoiq 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []