soda-ruby 0.2.13 → 0.2.15

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.
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.