soda-ruby 0.2.13 → 0.2.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 465ea1cbe79b189bc29e2798e6e907e677a21963
4
- data.tar.gz: d1c223e502052c9a07e34c95298ffdc237660b4c
3
+ metadata.gz: e08ae803c8dea78e00b08a07bc2be1cc4b87cd95
4
+ data.tar.gz: a9e5a9781c7fcfd40f599698128ed84063bee1d1
5
5
  SHA512:
6
- metadata.gz: db13c563d0055fcfdaa4ded0d8bf56874e0346085b0b10a2ec4165d633c6d292c0abee3f334940629d416f2e7f77b4a52d5e1545b71583a808a78739575ced2a
7
- data.tar.gz: 4a09101c6259b561b5ade89efc45d2ed39ee8e5231d2e212efa982174848c58832594a43d56ca6e592ccfeba0a8b5946b979eb439ce4cde978949266201ad6bb
6
+ metadata.gz: 70975c06355fbcb43a20571dc20d2c0e75ff3f197b59977bd6adaf804f8069e75dd465b311addd7691017074e41aec6474d0f07b6ad19f227bbd286719cc7498
7
+ data.tar.gz: ea997e8681e790a13e0b59f34e196d62367240a7c15929389e07f2536343f719d7098dcb3a535f85555b37b1e403038f729a4c1ba230f28bae0a8ec3f9bbceec
data/README.mkd CHANGED
@@ -18,10 +18,30 @@ Create a new client. Register for an application token at <http://dev.socrata.co
18
18
  client = SODA::Client.new({:domain => "explore.data.gov", :app_token => "CGxadgoQlgQSev4zyUh5aR5J3"})
19
19
  ```
20
20
 
21
- Issue a simple query. `644b-gaut` is the identifier for the dataset we want to access:
21
+ Issue a filter query. `644b-gaut` is the identifier for the dataset we want to access. The return object is an array of [Hashie::Mash](https://github.com/intridea/hashie) objects:
22
22
 
23
23
  ```ruby
24
24
  response = client.get("644b-gaut", {"$limit" => 1, :namelast => "WINFREY", :namefirst => "OPRAH"})
25
25
 
26
- => [#<Hashie::Mash appt_end_date="12/3/09 23:59" appt_made_date="12/2/09 18:05" appt_start_date="12/3/09 9:30" caller_name_first="SALLY" caller_name_last="ARMBRUSTER" last_updatedby="J7" lastentrydate="12/2/09 18:05" meeting_loc="WH" meeting_room="DIP ROOM" namefirst="OPRAH" namelast="WINFREY" post="WIN" release_date=1269586800 terminal_suffix="J7" total_people="10" type_of_access="VA" uin="U60816" visitee_namefirst="SEMONTI" visitee_namelast="STEPHENS">]
26
+ #=> [#<Hashie::Mash appt_end_date="12/3/09 23:59" appt_made_date="12/2/09 18:05" appt_start_date="12/3/09 9:30" caller_name_first="SALLY" caller_name_last="ARMBRUSTER" last_updatedby="J7" lastentrydate="12/2/09 18:05" meeting_loc="WH" meeting_room="DIP ROOM" namefirst="OPRAH" namelast="WINFREY" post="WIN" release_date=1269586800 terminal_suffix="J7" total_people="10" type_of_access="VA" uin="U60816" visitee_namefirst="SEMONTI" visitee_namelast="STEPHENS">]
27
27
  ```
28
+
29
+ You can use other simple query SoQL methods found here: <http://dev.socrata.com/docs/queries.html>
30
+
31
+ ```ruby
32
+ client = SODA::Client.new({:domain => "soda.demo.socrata.com"})
33
+ magnitude_response = client.get("4tka-6guv", {"$where" => "magnitude > '3.0'"})
34
+
35
+ #=> [#<Hashie::Mash datetime="2012-09-14T09:28:55" depth="20" earthquake_id="12258012" location=#<Hashie::Mash latitude="19.7859" longitude="-64.0849" needs_recoding=false> magnitude="3.1" number_of_stations="6" region="north of the Virgin Islands" source="pr" version="0">, #<Hashie::Mash datetime="2012-09-14T07:58:39" depth="74" earthquake_id="12258011" location=#<Hashie::Mash latitude="19.5907" longitude="-64.1723" needs_recoding=false> magnitude="3.3" number_of_stations="4" region="Virgin Islands region" source="pr" version="0">, ... ]
36
+
37
+ datetime_response = client.get("4tka-6guv", {"$where" => "datetime > '2012-09-14T09:28:55' AND datetime < '2012-12-25T09:00:00'"})
38
+
39
+ #=> [#<Hashie::Mash datetime="2012-09-14T10:10:19" depth="8.2" earthquake_id="00388609" location=#<Hashie::Mash latitude="36.9447" longitude="-117.6778" needs_recoding=false> magnitude="1.7" number_of_stations="29" region="Northern California" source="nn" version="9">, #<Hashie::Mash datetime="2012-09-14T10:06:11" depth="6.4" earthquake_id="00388607" location=#<Hashie::Mash latitude="36.9417" longitude="-117.6903" needs_recoding=false> magnitude="1.7" number_of_stations="29" region="Central California" source="nn" version="9">, ... ]
40
+ ```
41
+
42
+ All the field names have built in getter methods since the objects are Hashie::Mashes.
43
+
44
+ ```ruby
45
+ magnitude_response.first.number_of_stations #=> "6"
46
+ ```
47
+ *Note that the return value is a string object.*
@@ -1 +1 @@
1
- require "soda/client"
1
+ require 'soda/client'
@@ -10,9 +10,18 @@ require 'uri'
10
10
  require 'json'
11
11
  require 'cgi'
12
12
  require 'hashie'
13
+ require 'sys/uname'
14
+ require 'soda/version'
15
+ include Sys
13
16
 
14
17
  module SODA
15
18
  class Client
19
+ class << self
20
+ def generate_user_agent
21
+ "soda-ruby/#{SODA::VERSION} (#{Uname.uname.sysname}/#{Uname.uname.release}; Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
22
+ end
23
+ end
24
+
16
25
  ##
17
26
  #
18
27
  # Creates a new SODA client.
@@ -34,7 +43,8 @@ module SODA
34
43
  # client = SODA::Client.new({ :domain => "data.agency.gov", :app_token => "CGxarwoQlgQSev4zyUh5aR5J3" })
35
44
  #
36
45
  def initialize(config = {})
37
- @config = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
46
+ @config = Hashie.symbolize_keys! config
47
+ @user_agent = SODA::Client.generate_user_agent
38
48
  end
39
49
 
40
50
  ##
@@ -114,120 +124,127 @@ module SODA
114
124
  connection(:delete, resource, body, params)
115
125
  end
116
126
 
117
- def post_form(path, fields = {}, params = {})
127
+ def post_form(resource, body = {}, params = {})
118
128
  query = query_string(params)
119
- resource = resoure_path(path)
120
-
121
- # Create our request
122
- uri = URI.parse("https://#{@config[:domain]}#{resource}.json?#{query}")
123
- http = build_http_client(uri.host, uri.port)
129
+ path = resource_path(resource)
130
+ uri = URI.parse("https://#{@config[:domain]}#{path}?#{query}")
124
131
 
125
132
  request = Net::HTTP::Post.new(uri.request_uri)
126
- request.add_field("X-App-Token", @config[:app_token])
127
- request.set_form_data(fields)
133
+ add_default_headers_to_request(request)
134
+ request.set_form_data(body)
128
135
 
129
136
  # Authenticate if we're supposed to
130
- if @config[:username]
131
- request.basic_auth @config[:username], @config[:password]
132
- end
137
+ authenticate(request)
133
138
 
134
139
  # BAM!
135
- return handle_response(http.request(request))
140
+ http = build_http_client(uri.host, uri.port)
141
+ handle_response(http.request(request))
136
142
  end
137
143
 
138
144
  private
139
- def query_string(params)
140
- # Create query string of escaped key, value pairs
141
- return params.collect{ |key, val| "#{key}=#{CGI::escape(val.to_s)}" }.join("&")
142
- end
143
145
 
144
- def resource_path(resource)
145
- # If we didn't get a full path, assume "/resource/"
146
- if !resource.start_with?("/")
147
- resource = "/resource/" + resource
148
- end
146
+ def query_string(params)
147
+ # Create query string of escaped key, value pairs
148
+ params.map { |key, val| "#{key}=#{CGI.escape(val.to_s)}" }.join('&')
149
+ end
149
150
 
150
- # Check to see if we were given an output type
151
- extension = ".json"
152
- if matches = resource.match(/^(.+)(\.\w+)$/)
153
- resource = matches.captures[0]
154
- extension = matches.captures[1]
155
- end
151
+ def resource_path(resource)
152
+ # If we didn't get a full path, assume "/resource/"
153
+ resource = '/resource/' + resource unless resource.start_with?('/')
156
154
 
157
- return resource + extension
155
+ # Check to see if we were given an output type
156
+ extension = '.json'
157
+ if matches = resource.match(/^(.+)(\.\w+)$/)
158
+ resource = matches.captures[0]
159
+ extension = matches.captures[1]
158
160
  end
159
161
 
160
- def handle_response(response)
161
- # Check our response code
162
- if !["200", "202"].include? response.code
163
- raise "Error in request: #{response.body}"
162
+ resource + extension
163
+ end
164
+
165
+ def handle_response(response)
166
+ # Check our response code
167
+ check_response_fail(response)
168
+ if response.body.nil? || response.body.empty?
169
+ return nil
170
+ elsif response['Content-Type'].include?('application/json')
171
+ # Return a bunch of mashes if we're JSON
172
+ response = JSON.parse(response.body, :max_nesting => false)
173
+ if response.is_a? Array
174
+ return response.map { |r| Hashie::Mash.new(r) }
164
175
  else
165
- if response.body.nil? || response.body.empty?
166
- return nil
167
- elsif response["Content-Type"].include?("application/json")
168
- # Return a bunch of mashes if we're JSON
169
- response = JSON::parse(response.body, :max_nesting => false)
170
- if response.is_a? Array
171
- return response.collect { |r| Hashie::Mash.new(r) }
172
- else
173
- return Hashie::Mash.new(response)
174
- end
175
- else
176
- # We don't partically care, just return the raw body
177
- return response.body
178
- end
176
+ return Hashie::Mash.new(response)
179
177
  end
178
+ else
179
+ # We don't partically care, just return the raw body
180
+ return response.body
180
181
  end
182
+ end
181
183
 
182
- def connection(method = "Get", resource = nil, body = nil, params = {})
183
- method = method.to_sym.capitalize
184
+ def check_response_fail(response)
185
+ return if %w(200 202).include? response.code
186
+ fail "Error in request: #{response.body}"
187
+ end
184
188
 
185
- query = query_string(params)
189
+ def connection(method = 'Get', resource = nil, body = nil, params = {})
190
+ method = method.to_sym.capitalize
186
191
 
187
- path = resource_path(resource)
192
+ query = query_string(params)
193
+ path = resource_path(resource)
194
+ uri = URI.parse("https://#{@config[:domain]}#{path}?#{query}")
188
195
 
189
- uri = URI.parse("https://#{@config[:domain]}#{path}?#{query}")
196
+ request = eval("Net::HTTP::#{method}").new(uri.request_uri)
197
+ add_default_headers_to_request(request)
190
198
 
191
- http = build_http_client(uri.host, uri.port)
192
- request = eval("Net::HTTP::#{method.capitalize}").new(uri.request_uri)
193
- request.add_field("X-App-Token", @config[:app_token])
199
+ # Authenticate if we're supposed to
200
+ authenticate(request)
194
201
 
195
- if method === :Post || :Put || :Delete
196
- request.content_type = "application/json"
197
- request.body = body.to_json(:max_nesting => false)
198
- end
202
+ http = request_by_method(method, body, request, uri)
203
+ send_request(method, http, request)
204
+ end
199
205
 
200
- # Authenticate if we're supposed to
206
+ def send_request(method, http, request)
207
+ return delete_method_response(method, http, request) if method === :Delete
208
+ handle_response(http.request(request))
209
+ end
201
210
 
202
- if @config[:username]
203
- request.basic_auth @config[:username], @config[:password]
204
- end
211
+ def delete_method_response(http, request)
212
+ response = http.request(request)
213
+ return response if response.code == '200'
214
+ fail "Error querying \"#{uri}\": #{response.body}"
215
+ end
205
216
 
206
- if method === :Delete
207
- response = http.request(request)
208
- # Check our response code
209
- if response.code != "200"
210
- raise "Error querying \"#{uri.to_s}\": #{response.body}"
211
- else
212
- # Return a bunch of mashes
213
- return response
214
- end
215
- else
216
- return handle_response(http.request(request))
217
- end
218
- end
217
+ def net_http_class(method)
218
+ Object.const_get("Net::HTTP::#{method}")
219
+ end
219
220
 
220
- def build_http_client(host, port)
221
- http = Net::HTTP.new(host, port)
222
- http.use_ssl = true
223
- if @config[:ignore_ssl]
224
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
225
- end
226
- if @config[:timeout]
227
- http.read_timeout = @config[:timeout]
228
- end
229
- http
221
+ def request_by_method(method, body, request, uri)
222
+ if method === :Post || :Put || :Delete
223
+ request.content_type = 'application/json'
224
+ request.body = body.to_json(:max_nesting => false)
230
225
  end
231
226
 
227
+ build_http_client(uri.host, uri.port)
228
+ end
229
+
230
+ def build_http_client(host, port)
231
+ http = Net::HTTP.new(host, port)
232
+ http.use_ssl = true
233
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @config[:ignore_ssl]
234
+ http.read_timeout = @config[:timeout] if @config[:timeout]
235
+ http
236
+ end
237
+
238
+ def authenticate(request)
239
+ return unless @config[:username]
240
+ # Authenticate if we're supposed to
241
+ request.basic_auth @config[:username], @config[:password]
242
+ end
243
+
244
+ def add_default_headers_to_request(request)
245
+ request.delete('User-Agent')
246
+ request.add_field('X-App-Token', @config[:app_token])
247
+ request.add_field('User-Agent', @user_agent)
248
+ end
232
249
  end
233
250
  end
@@ -1,3 +1,3 @@
1
1
  module SODA
2
- VERSION = "0.2.13"
2
+ VERSION = '0.2.15'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soda-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.13
4
+ version: 0.2.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Metcalf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-15 00:00:00.000000000 Z
11
+ date: 2015-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -24,13 +24,153 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- description: A simple wrapper for SODA 2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: multipart-post
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sys-uname
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: shoulda
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: minitest
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: test-unit
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: mocha
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: A simple wrapper for SODA 2.0. Includes an OmniAuth provider for OAuth
168
+ 2.0
28
169
  email: chris.metcalf@socrata.com
29
170
  executables: []
30
171
  extensions: []
31
172
  extra_rdoc_files: []
32
173
  files:
33
- - CHANGELOG.mkd
34
174
  - LICENSE
35
175
  - README.mkd
36
176
  - lib/omniauth-socrata.rb
@@ -57,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
197
  version: 1.3.6
58
198
  requirements: []
59
199
  rubyforge_project: soda-ruby
60
- rubygems_version: 2.2.2
200
+ rubygems_version: 2.4.5
61
201
  signing_key:
62
202
  specification_version: 4
63
203
  summary: Ruby for SODA 2.0
@@ -1,11 +0,0 @@
1
- 0.2.0 - Initial Public Release
2
- 0.2.1 - Point release to update gemspec dependencies
3
- ...
4
- 0.2.4 - Point release including tests that are now mocked properly
5
- 0.2.6 - Code cleanup from @raykao
6
- 0.2.7 - Removing dead code and an un-needed dependency
7
- 0.2.8 - Removing the nesting limit on the JSON parser
8
- 0.2.10 - Removing a nesting limit that we missed
9
- 0.2.11 - We weren't properly handling an empty payload response
10
- 0.2.12 - Added a global option to disable SSL checking from https://github.com/socrata/soda-ruby/pull/7
11
- 0.2.13 - Added a global :timeout option to override the default Net:HTTP timeout, and accepting 202 as an "OK" response code, which should only occur during import.