policymap_wrap 0.1.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Gemini SBS, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,154 @@
1
+ = PolicyMap Wrap
2
+
3
+ Ruby wrapper around the PolicyMap API.
4
+
5
+ == Notes
6
+
7
+ PolicyMap APIs are custom designed, so your mileage may vary depending on your API.
8
+
9
+ == Usage
10
+
11
+ Before you can perform searches, you must first setup your PolicyMap credentials:
12
+
13
+ PolicyMap::Client.set_credentials(<account_id>)
14
+
15
+ There are three types of searches: query, boundary and indicator.
16
+ Each search is performed as follows, respectively:
17
+
18
+ PolicyMap::Client.query_search(<search_options>)
19
+ PolicyMap::Client.boundary_search(<search_options>)
20
+ PolicyMap::Client.indicator_search(<search_options>)
21
+
22
+ The search options (required and optional) will vary based on the type of search you are performing.
23
+
24
+ === PolicyMap::Client.query_search(<search_options>)
25
+
26
+ A +:search+ type of search is a free form query that *returns an array of hashes (with symbolized keys)* each containing the
27
+ boundary id of each match.
28
+
29
+ Required search options:
30
+
31
+ :query => "some sort of search string (eg, a city name: 'miami')"
32
+ :boundary_types => [:city, :zip] # Array or single boundary type
33
+
34
+ Required search options for *some* boundary types:
35
+
36
+ :state => "CA" # state abbreviation
37
+ :county => "Miami Dade"
38
+ :census_tract => 35525 # Numeric representing a census tract
39
+
40
+ Optional search options:
41
+
42
+ :max => 25 # Max number of results in the resultset
43
+
44
+ === PolicyMap::Client.boundary_search(<search_options>)
45
+
46
+ A +:boundary+ search *returns a hash (with symbolized keys)* containing a MultiPolygon.
47
+
48
+ Required search options:
49
+
50
+ :boundary_types => [:city, :zip, :state] # Can only specify 0 or 1 boundary type
51
+ # if boundary IDs (below) are also specified
52
+
53
+ Other search options:
54
+
55
+ :boundary_ids => [1024944, 1024989] # Array of boundary IDs
56
+ :lat => 33.805094 # Only to be used if boundary_ids (above) is not specified
57
+ :lng => -118.353717
58
+
59
+ === PolicyMap::Client.indicator_search(<search_options>)
60
+
61
+ An +:indicator+ type of search *returns a hash (with symbolized keys)* containing indicator data for the specified boundaries.
62
+
63
+ Required search options:
64
+
65
+ :boundary_types => [:city, :zip, :state] # Can only specify 0 or 1 boundary type
66
+ # if boundary IDs (below) are also specified
67
+ :indicators => [:total_population, :percent_asian]
68
+
69
+ Other search options:
70
+
71
+ :boundary_ids => [1024944, 1024989] # Array of boundary IDs
72
+ :lat => 33.805094 # Only to be used if boundary_ids (above) is not specified
73
+ :lng => -118.353717
74
+
75
+ === Available Boundary Types
76
+
77
+ :state
78
+ :county
79
+ :city
80
+ :zip
81
+ :census_tract
82
+ :block_group
83
+ :congressional_district
84
+ :assembly_district
85
+ :senate_district
86
+ :all # includes all boundary types
87
+
88
+ === Available Indicators
89
+
90
+ Population
91
+
92
+ :total_population
93
+ :percent_african_american
94
+ :percent_asian
95
+ :percent_pacific_islander
96
+ :percent_hispanic
97
+ :percent_native_american
98
+ :percent_mixed_race
99
+ :percent_under_18
100
+ :percent_65_or_older
101
+ :percent_foreign_born
102
+ :percent_disabled
103
+
104
+ Education
105
+
106
+ :percent_high_school_or_less
107
+ :percent_college_degree
108
+ :percent_graduate_degree
109
+
110
+ Housing
111
+
112
+ :median_home_value
113
+ :median_rent
114
+ :percent_moved_in_since_1990
115
+ :percent_homeowners
116
+ :vacancy_rate
117
+
118
+ Income
119
+
120
+ :median_household_income
121
+ :poverty_rate
122
+ :percent_households_wo_car
123
+ :average_vehicles_per_household
124
+ :percent_who_commute_to_work_using_public_transit
125
+ :unemployment_rate
126
+
127
+ Industry Concentrations
128
+
129
+ :independent_artists
130
+ :performing_arts_and_spectator_sports
131
+ :movie_and_sound_industries
132
+ :mueseums_and_historical_sites
133
+ :publishing_industries
134
+ :broadcasting
135
+ :other_info_services
136
+
137
+ Other
138
+
139
+ :all # includes all indicators
140
+
141
+ == Dependencies
142
+
143
+ PolicyMap Wrap stands on the shoulders of giants:
144
+
145
+ * {yajl-ruby}[http://github.com/brianmario/yajl-ruby] (Ruby wrapper around the great {yajl}[http://lloyd.github.com/yajl])
146
+ * {curb}[http://github.com/taf2/curb] (Ruby wrapper around the great {libcurl}[http://curl.haxx.se/])
147
+
148
+ == Copyright
149
+
150
+ Copyright (c) 2010 Gemini SBS. See LICENSE for details.
151
+
152
+ == Authors
153
+
154
+ * {Mauricio Gomes}[http://github.com/mgomes]
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/policymap.rb ADDED
@@ -0,0 +1,2 @@
1
+ # So you can require "policymap" instead of "policymap_wrap"
2
+ require "policymap_wrap"
@@ -0,0 +1,22 @@
1
+ require 'uri'
2
+ require 'yajl/json_gem'
3
+ require 'curb'
4
+
5
+ require 'policymap_wrap/connection'
6
+ require 'policymap_wrap/endpoint'
7
+ require 'policymap_wrap/hash_utils'
8
+ require 'policymap_wrap/client'
9
+
10
+ module PolicyMap
11
+ REALM = "http://staging.www.policymap.com"
12
+ VERSION = File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
13
+
14
+ class PolicyMapError < StandardError; end
15
+ class InsufficientArgsForSearch < PolicyMapError; end
16
+ class Unauthorized < PolicyMapError; end
17
+ class NotFound < PolicyMapError; end
18
+ class ServerError < PolicyMapError; end
19
+ class Unavailable < PolicyMapError; end
20
+ class DecodeError < PolicyMapError; end
21
+ class NoConnectionEstablished < PolicyMapError; end
22
+ end
@@ -0,0 +1,126 @@
1
+ module PolicyMap
2
+
3
+ class Client
4
+
5
+ BOUNDARY_TYPES = { :state => 2, :county => 4, :city => 16, :zip => 8, :census_tract => 6,
6
+ :block_group => 15, :congressional_district => 23, :assembly_district => 48,
7
+ :senate_district => 49, :all => 'all' }
8
+
9
+ INDICATORS = { :total_population => 9840661, :percent_african_american => 9840139, :percent_asian => 9840102,
10
+ :percent_pacific_islander => 9840497, :percent_hispanic => 9840238, :percent_native_american => 9840708,
11
+ :percent_mixed_race => 9840447, :percent_under_18 => 9840423, :percent_65_or_older => 9840365,
12
+ :percent_foreign_born => 9840645, :percent_disabled => 9840630, :percent_high_school_or_less => 9840299,
13
+ :percent_college_degree => 9840342, :percent_graduate_degree => 9840503, :median_home_value => 9840587,
14
+ :median_rent => 9840655, :percent_moved_in_since_1990 => 9840118, :percent_homeowners => 9840172,
15
+ :vacancy_rate => 9840676, :median_household_income => 9840169, :poverty_rate => 9840120,
16
+ :percent_households_wo_car => 0, :average_vehicles_per_household => 9845668,
17
+ :percent_who_commute_to_work_using_public_transit => 9845660, :unemployment_rate => 9841103,
18
+ :independent_artists => 9618303, :performing_arts_and_spectator_sports => 9584608,
19
+ :movie_and_sound_industries => 9584731, :mueseums_and_historical_sites => 9584676,
20
+ :publishing_industries => 9584638, :broadcasting => 9584691, :other_info_services => 9584624, :all => 'all' }
21
+
22
+ @@connection = nil
23
+ @@debug = false
24
+ @@default_options = nil
25
+
26
+ class << self
27
+
28
+ def set_credentials(client_id)
29
+ @@default_options = { :id => client_id, :ty => 'data', :f => 'j' }
30
+ @@connection = Connection.new(client_id)
31
+ @@connection.debug = @@debug
32
+ true
33
+ end
34
+
35
+ def debug=(debug_flag)
36
+ @@debug = debug_flag
37
+ @@connection.debug = @@debug if @@connection
38
+ end
39
+
40
+ def debug
41
+ @@debug
42
+ end
43
+
44
+ def query_search(*args)
45
+ default_options = @@default_options
46
+ default_options[:t] = "sch"
47
+
48
+ options = extract_options!(args)
49
+
50
+ raise InsufficientArgsForSearch unless options.has_key?(:boundary_types) && options.has_key?(:query)
51
+
52
+ options[:boundary_types] = Array(options[:boundary_types]).collect {|bt| BOUNDARY_TYPES[bt] }.join(',')
53
+ HashUtils.rename_key!(options, :boundary_types, :bt)
54
+ HashUtils.rename_key!(options, :query, :s)
55
+ HashUtils.rename_key!(options, :state, :st) if options.has_key?(:state)
56
+ HashUtils.rename_key!(options, :county, :co) if options.has_key?(:county)
57
+ HashUtils.rename_key!(options, :census_tract, :ct) if options.has_key?(:census_tract)
58
+
59
+ options = default_options.merge(options)
60
+
61
+ result = get(Endpoint.endpoint_url, options)
62
+ result['sch'].collect {|hsh| HashUtils.symbolize_keys(hsh) }
63
+ end
64
+
65
+ def boundary_search(*args)
66
+ default_options = @@default_options
67
+ default_options[:t] = "bnd"
68
+
69
+ options = extract_options!(args)
70
+
71
+ raise InsufficientArgsForSearch unless options.has_key?(:boundary_types) || options.has_key?(:boundary_ids)
72
+
73
+ options[:boundary_types] = Array(options[:boundary_types]).collect {|bt| BOUNDARY_TYPES[bt] }.join(',') if options.has_key?(:boundary_types)
74
+ options[:boundary_ids] = Array(options[:boundary_ids]).join(',') if options.has_key?(:boundary_ids)
75
+ HashUtils.rename_key!(options, :boundary_types, :bt) if options.has_key?(:boundary_types)
76
+ HashUtils.rename_key!(options, :boundary_ids, :bi) if options.has_key?(:boundary_ids)
77
+ HashUtils.rename_key!(options, :lng, :lon) if options.has_key?(:lng)
78
+
79
+ options = default_options.merge(options)
80
+
81
+ result = get(Endpoint.endpoint_url, options)
82
+ HashUtils.recursively_symbolize_keys(result["bnd"])
83
+ end
84
+
85
+ def indicator_search(*args)
86
+ default_options = @@default_options
87
+ default_options[:t] = "ind"
88
+
89
+ options = extract_options!(args)
90
+
91
+ raise InsufficientArgsForSearch unless options.has_key?(:indicators) && (options.has_key?(:boundary_types) || options.has_key?(:boundary_ids))
92
+
93
+ options[:indicators] = Array(options[:indicators]).collect {|i| INDICATORS[i] }.join(',')
94
+ options[:boundary_types] = Array(options[:boundary_types]).collect {|bt| BOUNDARY_TYPES[bt] }.join(',') if options.has_key?(:boundary_types)
95
+ options[:boundary_ids] = Array(options[:boundary_ids]).join(',') if options.has_key?(:boundary_ids)
96
+ HashUtils.rename_key!(options, :indicators, :ii)
97
+ HashUtils.rename_key!(options, :boundary_types, :bt) if options.has_key?(:boundary_types)
98
+ HashUtils.rename_key!(options, :boundary_ids, :bi) if options.has_key?(:boundary_ids)
99
+ HashUtils.rename_key!(options, :lng, :lon) if options.has_key?(:lng)
100
+
101
+ options = default_options.merge(options)
102
+
103
+ result = get(Endpoint.endpoint_url, options)
104
+ HashUtils.recursively_symbolize_keys(result["ind"])
105
+ end
106
+
107
+ def get(endpoint, data=nil)
108
+ raise NoConnectionEstablished if @@connection.nil?
109
+ @@connection.get endpoint, data
110
+ end
111
+
112
+ private
113
+
114
+ def extract_options!(args)
115
+ if args.last.is_a?(Hash)
116
+ return args.pop
117
+ else
118
+ return {}
119
+ end
120
+ end
121
+
122
+ end
123
+
124
+ end
125
+
126
+ end
@@ -0,0 +1,136 @@
1
+ module PolicyMap
2
+
3
+ class Connection
4
+
5
+ attr_accessor :debug
6
+ attr_reader :client_id
7
+
8
+ def initialize(client_id)
9
+ @client_id = client_id
10
+ @debug = false
11
+ end
12
+
13
+ def get(endpoint, data=nil)
14
+ request :get, endpoint, data
15
+ end
16
+
17
+ class Response
18
+
19
+ attr_reader :code, :header, :body, :message
20
+
21
+ HTTP_RESPONSES = { '100' => 'Continue', '101' => 'SwitchProtocol', '200' => 'OK', '201' => 'Created', '202' => 'Accepted', '203' => 'NonAuthoritativeInformation',
22
+ '204' => 'NoContent', '205' => 'ResetContent', '206' => 'PartialContent', '300' => 'MultipleChoice', '301' => 'MovedPermanently',
23
+ '302' => 'Found', '303' => 'SeeOther', '304' => 'NotModified', '305' => 'UseProxy', '307' => 'TemporaryRedirect', '400' => 'BadRequest',
24
+ '401' => 'Unauthorized', '402' => 'PaymentRequired', '403' => 'Forbidden', '404' => 'NotFound', '405' => 'MethodNotAllowed',
25
+ '406' => 'NotAcceptable', '407' => 'ProxyAuthenticationRequired', '408' => 'RequestTimeOut', '409' => 'Conflict', '410' => 'Gone',
26
+ '411' => 'LengthRequired', '412' => 'PreconditionFailed', '413' => 'RequestEntityTooLarge', '414' => 'RequestURITooLong',
27
+ '415' => 'UnsupportedMediaType', '416' => 'RequestedRangeNotSatisfiable', '417' => 'ExpectationFailed', '500' => 'InternalServerError',
28
+ '501' => 'NotImplemented', '502' => 'BadGateway', '503' => 'ServiceUnavailable', '504' => 'GatewayTimeOut', '505' => 'VersionNotSupported' }
29
+
30
+ def initialize(http_client)
31
+ @code = http_client.response_code
32
+ @header = http_client.header_str.is_a?(String) ? parse_headers(http_client.header_str) : http_client.header_str
33
+ @body = http_client.body_str
34
+ @message = HTTP_RESPONSES[@code.to_s]
35
+ end
36
+
37
+ private
38
+
39
+ def parse_headers(header_string)
40
+ header_lines = header_string.split($/)
41
+ header_lines.shift
42
+ header_lines.inject({}) do |hsh, line|
43
+ whole_enchillada, key, value = /^(.*?):\s*(.*)$/.match(line.chomp).to_a
44
+ hsh[key] = value unless whole_enchillada.nil?
45
+ hsh
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ private
52
+
53
+ def request(method, endpoint, data)
54
+ headers = { 'User-Agent' => "PolicyMap Ruby Client v#{VERSION}" }
55
+
56
+ if [:get].include?(method) && !data.nil?
57
+ endpoint = endpoint + '?' + build_query(data)
58
+ end
59
+
60
+ if debug
61
+ puts "request: #{method.to_s.upcase} #{endpoint}"
62
+ puts "headers:"
63
+ headers.each do |key, value|
64
+ puts "#{key}=#{value}"
65
+ end
66
+ end
67
+
68
+ response = send_request(method, endpoint, headers)
69
+
70
+ if debug
71
+ puts "\nresponse: #{response.code}"
72
+ puts "headers:"
73
+ response.header.each do |key, value|
74
+ puts "#{key}=#{value}"
75
+ end
76
+ puts "body:"
77
+ puts response.body
78
+ end
79
+
80
+ raise_errors(response)
81
+
82
+ if response.body.empty?
83
+ content = nil
84
+ else
85
+ begin
86
+ content = JSON.parse(response.body)
87
+ rescue JSON::ParserError
88
+ raise DecodeError, "content: <#{response.body}>"
89
+ end
90
+ end
91
+
92
+ content
93
+ end
94
+
95
+ def build_query(data)
96
+ data = data.to_a if data.is_a?(Hash)
97
+ data.map do |key, value|
98
+ [key.to_s, URI.escape(value.to_s)].join('=')
99
+ end.join('&')
100
+ end
101
+
102
+ def send_request(method, endpoint, headers)
103
+ if method == :get
104
+ @http_client = Curl::Easy.new(endpoint) do |c|
105
+ c.headers = headers
106
+ end
107
+ end
108
+
109
+ @http_client.perform
110
+
111
+ Response.new(@http_client)
112
+ end
113
+
114
+ def raise_errors(response)
115
+ response_description = "(#{response.code}): #{response.message}"
116
+ response_description += " - #{response.body}" unless response.body.empty?
117
+
118
+ case response.code.to_i
119
+ when 401
120
+ raise Unauthorized
121
+ when 404
122
+ raise NotFound
123
+ when 500
124
+ raise ServerError, "PolicyMap had an internal error. Please let them know. #{response_description}"
125
+ when 502..503
126
+ raise Unavailable, response_description
127
+ else
128
+ unless response.code.to_i == 200
129
+ raise PolicyMapError, response_description
130
+ end
131
+ end
132
+ end
133
+
134
+ end
135
+
136
+ end
@@ -0,0 +1,15 @@
1
+ module PolicyMap
2
+
3
+ class Endpoint
4
+
5
+ class << self
6
+
7
+ def endpoint_url
8
+ [REALM, 's/'].join('/')
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,33 @@
1
+ module PolicyMap
2
+
3
+ class HashUtils
4
+
5
+ def self.rename_key!(hash, old_key, new_key)
6
+ hash[new_key] = hash.delete(old_key)
7
+ hash
8
+ end
9
+
10
+ def self.symbolize_keys(hash)
11
+ hash.inject({}) do |options, (key, value)|
12
+ options[(key.to_sym rescue key) || key] = value
13
+ options
14
+ end
15
+ end
16
+
17
+ def self.recursively_symbolize_keys(object)
18
+ if object.is_a? Hash
19
+ symbolized_hash = symbolize_keys(object)
20
+ symbolized_hash.each do |key, value|
21
+ symbolized_hash[key] = recursively_symbolize_keys(value)
22
+ end
23
+ symbolized_hash
24
+ elsif object.is_a? Array
25
+ object.map {|value| recursively_symbolize_keys(value) }
26
+ else
27
+ object
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "PolicymapWrap" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'policymap_wrap'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: policymap_wrap
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Mauricio Gomes
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-27 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: yajl-ruby
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 0
32
+ - 7
33
+ - 7
34
+ version: 0.7.7
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: curb
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 105
46
+ segments:
47
+ - 0
48
+ - 7
49
+ - 7
50
+ - 1
51
+ version: 0.7.7.1
52
+ type: :runtime
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ name: rspec
56
+ prerelease: false
57
+ requirement: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 13
63
+ segments:
64
+ - 1
65
+ - 2
66
+ - 9
67
+ version: 1.2.9
68
+ type: :development
69
+ version_requirements: *id003
70
+ description: Ruby wrapper around the PolicyMap API. Your API may vary.
71
+ email: mauricio@geminisbs.com
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ extra_rdoc_files:
77
+ - LICENSE
78
+ - README.rdoc
79
+ files:
80
+ - LICENSE
81
+ - README.rdoc
82
+ - VERSION
83
+ - lib/policymap.rb
84
+ - lib/policymap_wrap.rb
85
+ - lib/policymap_wrap/client.rb
86
+ - lib/policymap_wrap/connection.rb
87
+ - lib/policymap_wrap/endpoint.rb
88
+ - lib/policymap_wrap/hash_utils.rb
89
+ - spec/policymap_wrap_spec.rb
90
+ - spec/spec_helper.rb
91
+ has_rdoc: true
92
+ homepage: http://github.com/geminisbs/policymap_wrap
93
+ licenses: []
94
+
95
+ post_install_message:
96
+ rdoc_options:
97
+ - --charset=UTF-8
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ hash: 3
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ requirements: []
119
+
120
+ rubyforge_project:
121
+ rubygems_version: 1.3.7
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: Ruby wrapper around the PolicyMap API
125
+ test_files:
126
+ - spec/policymap_wrap_spec.rb
127
+ - spec/spec_helper.rb