openapply 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,399 @@
1
+ module Get
2
+
3
+ # Creates a custom query (non-recursive) to get a list of students summaries
4
+ # matching the allowed attribute's criteria
5
+ #
6
+ # ==== Attributes
7
+ # * +status+ - match status (be sure it is in the list of OpenApply status)
8
+ # * +since_id+ - get all ids matching the criteria LARGER than the given number
9
+ # * +since_date+ - get all records updated after the given date (YYYY-MM-DD) or
10
+ # Date and Time (YYYY-MM-DD HH:MM:SS) - 24 hour clock (not sure about timeszone)
11
+ # * +count+ - return a custom number of records (no more than 1000)
12
+ #
13
+ # ==== Example code
14
+ # @demo = Openapply.new
15
+ # # return: any status (nil), any id greater than 95 updated since 2017-01-01 &
16
+ # # return only 2 records at a time
17
+ # @demo.custom_students_query(nil, since_id=95, since_date=2017-01-01, count=2)
18
+ #
19
+ # ==== Return Format
20
+ # { :students=>
21
+ # [{:id=>96,
22
+ # :serial_number=>86,
23
+ # :custom_id=>"86",
24
+ # :applicant_id=>"00000086",
25
+ # :email=>"Jerry.Patel@eduvo.com",
26
+ # :first_name=>"Jerry",
27
+ # :last_name=>"Patel",
28
+ # ...,
29
+ # :sibling_ids=>[],
30
+ # :updated_at=>"2017-07-11T14:46:44.000+08:00",
31
+ # :...,
32
+ # :parent_ids=>[267, 268]},
33
+ # {:id=>98,
34
+ # :serial_number=>87,
35
+ # :custom_id=>"87",
36
+ # :applicant_id=>"00000087",
37
+ # :email=>"Robin.Barnes@eduvo.com",
38
+ # :first_name=>"Robin",
39
+ # :last_name=>"Barnes",
40
+ # :sibling_ids=>[],
41
+ # :updated_at=>"2017-07-11T14:46:44.000+08:00",
42
+ # ...,
43
+ # :profile_photo=>
44
+ # "https://openapply-sandbox-devel-01.s3.amazonaws.com/uploads/student/avatar/000/000/098/f_rep.jpg?v=1499755604",
45
+ # :profile_photo_updated_at=>"2017-07-11T14:46:44.000+08:00",
46
+ # :parent_ids=>[406, 407]}],
47
+ # :linked=>
48
+ # {:parents=>
49
+ # [{:id=>267,
50
+ # :serial_number=>256,
51
+ # :custom_id=>"256",
52
+ # :name=>"Jane Patel",
53
+ # :first_name=>"Jane",
54
+ # :last_name=>"Patel",
55
+ # ...,
56
+ # :profile_photo=>
57
+ # "https://openapply-sandbox-devel-01.s3.amazonaws.com/uploads/parent/avatar/000/000/267/patel_mom.jpg?v=1499755607",
58
+ # :profile_photo_updated_at=>"2017-07-11T14:46:47.000+08:00",
59
+ # :parent_id=>"256",
60
+ # :custom_fields=>
61
+ # {:title=>"",
62
+ # :treat_parent_as_emergency_contact=>"Yes",
63
+ # :home_telephone=>"",
64
+ # ...,
65
+ # :parent_residency=>"Citizen"}},
66
+ # { ... },
67
+ # {:id=>407,
68
+ # :serial_number=>nil,
69
+ # :custom_id=>nil,
70
+ # :name=>"Boris Barnes",
71
+ # :first_name=>"Boris",
72
+ # :last_name=>"Barnes",
73
+ # ...,
74
+ # :profile_photo=>
75
+ # "https://openapply-sandbox-devel-01.s3.amazonaws.com/uploads/parent/avatar/000/000/407/6e9b4e89-0aa8-413c-8239-2990ea6b0e6d.jpg?v=1499755608",
76
+ # :profile_photo_updated_at=>"2017-07-11T14:46:48.000+08:00",
77
+ # :parent_id=>nil,
78
+ # :custom_fields=>
79
+ # {:title=>nil,
80
+ # :treat_parent_as_emergency_contact=>"Yes",
81
+ # :mobile_phone=>"852 6565 1190",
82
+ # :home_telephone=>"852 4545 1190",
83
+ # ...,
84
+ # :parent_residency=>nil}}]},
85
+ # :meta=>{:pages=>170, :per_page=>"2"}}
86
+ def students_custom_query(status=nil, since_id=nil, since_date=nil, count=api_records)
87
+ return { error: "invalid count" } unless count.to_i >= 1
88
+
89
+ url = students_custom_url(status, since_id, since_date, count)
90
+ answer = oa_answer( url )
91
+ return { error: "nil answer" } if answer.nil?
92
+ return { error: "nil students" } if answer[:students].nil?
93
+ return { student_ids: [] } if answer[:students].empty?
94
+ return answer
95
+ end
96
+
97
+
98
+ # Builds a custom url (with domain) to get a list of students summaries matching
99
+ # the attribute's criteria (but not do a Query) - returns a URL
100
+ #
101
+ # ==== Attributes
102
+ # * +status+ - match status (be sure it is in the list of OpenApply status)
103
+ # * +since_id+ - get all ids matching the criteria LARGER than the given number
104
+ # * +since_date+ - get all records updated after the given date (YYYY-MM-DD) or
105
+ # Date and Time (YYYY-MM-DD HH:MM:SS) - 24 hour clock (not sure about timeszone)
106
+ # * +count+ - return a custom number of records (no more than 1000)
107
+ #
108
+ # ==== Example Code
109
+ # @demo = Openapply.new
110
+ # @demo.custom_students_url(status='applied', since_id=96, since_date='2017-01-25', count=2)
111
+ #
112
+ # ==== Return Format
113
+ # "/api/v1/students/?status=applied&since_id=96&since_date=2017-01-25&count=2&auth_token=319d9axxxxxxx"
114
+ def students_custom_url(status=nil, since_id=nil, since_date=nil, count=api_records)
115
+ url_options = []
116
+ url_options << "status=#{status}" unless status.to_s.eql? ""
117
+ url_options << "since_id=#{since_id}" unless since_id.to_s.eql? ""
118
+ url_options << "since_date=#{since_date}" unless since_date.to_s.eql? ""
119
+ url_options << "count=#{count}"
120
+ url_options << "auth_token=#{api_key}"
121
+
122
+ return "#{api_path}?#{url_options.join('&')}"
123
+ end
124
+
125
+
126
+ # returns a list of student ids that match a give status (this is recursive -
127
+ # so returns the entire list - even if that list is longer than the api_return_count)
128
+ #
129
+ # ==== Attributes
130
+ # * +status+ - match status (be sure it is in the list of OpenApply status)
131
+ #
132
+ # ==== Example code
133
+ # @demo = Openapply.new
134
+ # @demo.student_ids_by_status('applied')
135
+ #
136
+ # ==== Return Format
137
+ # {:student_ids=>[95, 106, 240, ..., 582]}
138
+ def student_ids_by_status(status)
139
+ answer = students_by_status(status)
140
+ return { error: "nil answer" } if answer.nil?
141
+ return { error: "nil students" } if answer[:students].nil?
142
+ return { student_ids: [] } if answer[:students].empty?
143
+
144
+ ids = answer[:students].map{ |l| l[:id] }
145
+ return { student_ids: ids }
146
+ end
147
+ alias_method :all_student_ids_by_status, :student_ids_by_status
148
+
149
+
150
+ # returns a list of student summaries (in OpenApply's format) that
151
+ # match a give status (this is recursive - so returns the entire list -
152
+ # even if that list is longer than the api_return_count)
153
+ #
154
+ # ==== Attributes
155
+ # * +status+ - match status (be sure it is in the list of OpenApply status)
156
+ #
157
+ # ==== Return Format
158
+ # {:students=>
159
+ # [{:id=>95,
160
+ # :serial_number=>85,
161
+ # :custom_id=>"85",
162
+ # :applicant_id=>"00000085",
163
+ # :email=>"Richard.Washington@eduvo.com",
164
+ # :first_name=>"Richard",
165
+ # :last_name=>"Washington",
166
+ # :name=>"Richard Washington",
167
+ # ...,
168
+ # :parent_ids=>[492, 493]},
169
+ # {:id=>106,
170
+ # :serial_number=>90,
171
+ # :custom_id=>"90",
172
+ # :applicant_id=>"00000090",
173
+ # :email=>"Henry.Epelbaum@eduvo.com",
174
+ # :first_name=>"Samuel",
175
+ # :last_name=>"Epelbaum",
176
+ # ...,
177
+ # :parent_ids=>[265, 266]}],
178
+ # :linked=>
179
+ # {:parents=>
180
+ # [{:id=>492,
181
+ # :serial_number=>nil,
182
+ # :custom_id=>nil,
183
+ # :name=>"Philippa Washington",
184
+ # :first_name=>"Philippa",
185
+ # :last_name=>"Washington",
186
+ # ...,
187
+ # :custom_fields=>
188
+ # {:title=>nil,
189
+ # :treat_parent_as_emergency_contact=>nil,
190
+ # :mobile_phone=>"852 6712 1196",
191
+ # :home_telephone=>"+852 9954 1179",
192
+ # ...,
193
+ # :parent_residency=>nil}},
194
+ # {:id=>493,
195
+ # :serial_number=>nil,
196
+ # :custom_id=>nil,
197
+ # :name=>"Fred Washington",
198
+ # :first_name=>"Fred",
199
+ # :last_name=>"Washington",
200
+ # ...,
201
+ # :address=>"High Street 110",
202
+ # :address_ii=>nil,
203
+ # :city=>"Hong Kong",
204
+ # :state=>nil,
205
+ # :postal_code=>nil,
206
+ # :country=>"Hong Kong",
207
+ # :email=>"fredw@eduvo.com",
208
+ # :parent_role=>"Father",
209
+ # :updated_at=>"2017-07-11T14:46:48.000+08:00",
210
+ # ...,
211
+ # :custom_fields=>
212
+ # {:title=>nil,
213
+ # :treat_parent_as_emergency_contact=>nil,
214
+ # :mobile_phone=>"+852 9954 1179",
215
+ # :home_telephone=>"+852 9954 1179",
216
+ # ...,
217
+ # :parent_residency=>nil}}]},
218
+ # :meta=>{:pages=>1, :per_page=>"100"}}
219
+ def students_by_status(status)
220
+ url = students_custom_url(status)
221
+ answer = oa_answer( url )
222
+ return { error: "no students found" } if answer[:students].nil?
223
+ return { students: [] } if answer[:students].empty?
224
+
225
+ page_number = answer[:meta][:pages]
226
+ return answer if page_number == 1
227
+
228
+ # inspect meta data -- loop until page = 1
229
+ all_students = answer[:students]
230
+ while page_number > 1
231
+ last_student = answer[:students].last
232
+ since_id = last_student[:id]
233
+ url = students_custom_url(status,since_id)
234
+ answer = oa_answer( url )
235
+ page_number = answer[:meta][:pages]
236
+ all_students += answer[:students]
237
+ end
238
+ return { students: all_students }
239
+ end
240
+ # alias_method :all_student_summaries_by_status, :students_by_status
241
+ alias_method :students, :students_by_status
242
+
243
+
244
+ # returns a list of student with all details (gaurdians & payments) that
245
+ # match a give status (this is recursive - so returns the entire list - even
246
+ # if that list is longer than the api_return_count)
247
+ #
248
+ # ==== Attributes
249
+ # * +status+ - match status (be sure it is in the list of OpenApply status)
250
+ #
251
+ # ==== Return Format
252
+ # {students: [
253
+ # {
254
+ # id=95,
255
+ # record: {},
256
+ # guardians: [],
257
+ # payments: []
258
+ # },
259
+ # {
260
+ # id=487,
261
+ # record: {},
262
+ # guardians: [],
263
+ # payments: []
264
+ # }
265
+ # ]}
266
+ # for example:
267
+ # :students=>
268
+ # [{:id=>"95",
269
+ # :record=>
270
+ # {:id=>95,
271
+ # :serial_number=>85,
272
+ # ...,
273
+ # :custom_fields=>
274
+ # {:language=>"English",
275
+ # :nationality=>"American (United States)",
276
+ # :referral_source=>"Friends",
277
+ # ...,
278
+ # :siblings_information=>
279
+ # [{:first_name=>"Jerry",
280
+ # :last_name=>"Washington",
281
+ # :gender=>"Male",
282
+ # :birth_date=>"2008-06-04"}],
283
+ # :emergency_contact=>[],
284
+ # :immunization_record=>[],
285
+ # :health_information=>[]},
286
+ # :parent_ids=>[492, 493]},
287
+ # :payments=>[],
288
+ # :guardians=>
289
+ # [{:id=>492,
290
+ # :serial_number=>nil,
291
+ # :custom_id=>nil,
292
+ # :name=>"Philippa Washington",
293
+ # :first_name=>"Philippa",
294
+ # :last_name=>"Washington",
295
+ # ...,
296
+ # :custom_fields=>
297
+ # {:title=>nil,
298
+ # :treat_parent_as_emergency_contact=>nil,
299
+ # :mobile_phone=>"852 6712 1196",
300
+ # :home_telephone=>"+852 9954 1179",
301
+ # ...,
302
+ # :parent_residency=>nil}},
303
+ # {:id=>493,
304
+ # :serial_number=>nil,
305
+ # :custom_id=>nil,
306
+ # :name=>"Fred Washington",
307
+ # :first_name=>"Fred",
308
+ # :last_name=>"Washington",
309
+ # ...,
310
+ # :custom_fields=>
311
+ # {:title=>nil,
312
+ # :treat_parent_as_emergency_contact=>nil,
313
+ # :mobile_phone=>"+852 9954 1179",
314
+ # :home_telephone=>"+852 9954 1179",
315
+ # ...,
316
+ # :parent_residency=>nil}}]},
317
+ # { ... },
318
+ # {:id=>"582",
319
+ # :record=>
320
+ # {:id=>582,
321
+ # :serial_number=>437,
322
+ # :custom_id=>nil,
323
+ # :applicant_id=>"00000437",
324
+ # :email=>"s3@example.com",
325
+ # :first_name=>"Ada",
326
+ # :last_name=>"Junior",
327
+ # ...,
328
+ # :profile_photo=>
329
+ # "https://openapply-sandbox-devel-01.s3.amazonaws.com/uploads/student/avatar/000/000/582/boy-01.jpg?v=1500883583",
330
+ # :profile_photo_updated_at=>"2017-07-24T16:06:23.000+08:00",
331
+ # :custom_fields=>
332
+ # {:language=>nil,
333
+ # :nationality=>nil,
334
+ # :referral_source=>nil,
335
+ # ...,
336
+ # :prior_school_list=>[],
337
+ # :immunization_record=>[],
338
+ # :health_information=>[]},
339
+ # :parent_ids=>[]},
340
+ # :payments=>[],
341
+ # :guardians=>[]}]}
342
+ def students_details_by_status(status)
343
+ ids = all_student_ids_by_status(status)
344
+ return { error: 'answer nil' } if ids.nil?
345
+ return { error: 'ids nil' } if ids[:student_ids].nil?
346
+ return { error: 'ids empty' } if ids[:student_ids].empty?
347
+
348
+ # loop through each student
349
+ error_ids = []
350
+ student_records = []
351
+ ids[:student_ids].each do |id|
352
+ # get each kids details w_billing
353
+ student = student_details_by_id( "#{id}" )
354
+
355
+ error_ids << id if student.nil? or
356
+ student[:student].nil? or
357
+ student[:student].empty?
358
+ student_records << student[:student] unless student.nil? or
359
+ student[:student].nil? or
360
+ student[:student].empty?
361
+ end
362
+
363
+ return { students: [], error_ids: error_ids } if student_records.empty?
364
+ return { students: student_records }
365
+ end
366
+ # alias_method :all_student_records_w_billing_by_status, :students_details_by_status
367
+ # alias_method :all_students_all_data_by_status, :students_details_by_status
368
+ alias_method :students_details, :students_details_by_status
369
+
370
+ def students_details_as_csv_by_status(status,keys)
371
+ # some code
372
+ end
373
+
374
+ # # TODO: build queries that collects changed by date
375
+ # # get summary info with a status (useful to get ids - no custom_fields)
376
+ # def students_by_since_id(since_id, status = nil, date = nil)
377
+ # url = "#{@api_path}?count=#{api_records}&auth_token=#{@api_key}"
378
+ # elsif date.nil? or date == ""
379
+ # url = "#{@api_path}?status=#{status}&count=#{api_records}&auth_token=#{@api_key}"
380
+ # else
381
+ # url = "#{@api_path}?status=#{status}&since_date=#{date}&count=#{api_records}&auth_token=#{@api_key}"
382
+ # end
383
+ # return oa_answer( url, options )
384
+ # end
385
+ #
386
+ #
387
+ # # TODO: build queries that collects changed by date
388
+ # # get summary info with a status (useful to get ids - no custom_fields)
389
+ # def student_summaries_by_since_date(since_date, since_id = nil, status = nil)
390
+ # url = "#{@api_path}?count=#{api_records}&auth_token=#{@api_key}"
391
+ # elsif since_date.nil? or since_date == ""
392
+ # url = "#{@api_path}?status=#{status}&count=#{api_records}&auth_token=#{@api_key}"
393
+ # else
394
+ # url = "#{@api_path}?status=#{status}&since_date=#{since_date}&count=#{@api_records}&auth_token=#{@api_key}"
395
+ # end
396
+ # return oa_answer( url, options )
397
+ # end
398
+
399
+ end
@@ -0,0 +1,3 @@
1
+ module Put
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ module Openapply
2
+ VERSION = "0.2.0"
3
+ end
data/lib/openapply.rb ADDED
@@ -0,0 +1,125 @@
1
+ require "openapply/get_students"
2
+ require "openapply/get_student"
3
+ require "openapply/version"
4
+ require "openapply/put"
5
+ require 'httparty'
6
+
7
+ module Openapply
8
+
9
+ # OpenApply is a service to manage admissions -
10
+ # this gem allows access to OpenApply API calls via HTTParty
11
+ #
12
+ class Client
13
+
14
+ # Contains the GET api calls
15
+ include Get
16
+ # Contains the PUT api calls
17
+ include Put
18
+ # Library to make the API calls with OpenApply
19
+ include HTTParty
20
+
21
+ # Defines OpenApply domain name from ENV-VARS
22
+ API_URL = (ENV['OA_BASE_URI'] || 'demo.openapply.com')
23
+
24
+ # Defines the OpenApply path from ENV-VARS - default is 5 seconds
25
+ API_TIMEOUT = (ENV['OA_TIMEOUT'].to_i || 5)
26
+
27
+ base_uri API_URL
28
+ default_timeout API_TIMEOUT
29
+
30
+ # Defines OpenApply domain name from ENV-VARS - for example:
31
+ # demo.openapply.com
32
+ def api_url
33
+ API_URL
34
+ end
35
+
36
+ # Defines http timeout from ENV-VARS - 5 sec is the default
37
+ def api_reply_count
38
+ API_TIMEOUT
39
+ end
40
+ alias_method :api_timeout, :api_reply_count
41
+
42
+ # Defines OpenApply secret access key with ENV-VARS
43
+ def api_key
44
+ ENV['OA_AUTH_TOKEN'] || 'demo_site_api_key'
45
+ end
46
+
47
+ # Defines the OpenApply path with ENV-VARS - default is for api_v1
48
+ # /api/v1/students/
49
+ def api_path
50
+ ENV['OA_API_PATH'] || "/api/v1/students/"
51
+ end
52
+ # alias_method :base_path, :api_path
53
+
54
+ # Defines the maximum records OpenApply should return with each api call
55
+ # with ENV-VARS - (code default is 100 - OpenApply default is 10)
56
+ def api_records
57
+ ENV['OA_REPLY_RECORDS'] || '100'
58
+ end
59
+ # alias_method :record_count, :api_max_records
60
+
61
+ # Handles httparty timeout errors - tries 3x before quitting
62
+ # https://stackoverflow.com/questions/26251422/handling-netreadtimeout-error-in-httparty
63
+ # TODO: figure out how to test time outs
64
+ def handle_timeouts
65
+ max_retries = 3
66
+ times_retried = 0
67
+ begin
68
+ yield
69
+ rescue Net::ReadTimeout => error
70
+ if times_retried < max_retries
71
+ times_retried += 1
72
+ # puts "TIMEOUT RETRY: #{times_retried} of #{max_retries} - USING: #{yield.inspect}"
73
+ retry
74
+ else
75
+ # puts "TIME-OUT URI FAILED: #{yield.inspect}"
76
+ { error: "SITE TIMEOUT - 3 FAILURES USING: #{yield.inspect}" }
77
+ end
78
+ end
79
+ end
80
+
81
+ # Does the actual api call to OpenApply
82
+ #
83
+ # ==== Attributes
84
+ # * +url+ - this is the url to do the call
85
+ # /api/v1/students/95?auth_token=demo_site_api_key
86
+ # is the url passed when wanting to do the following cli api call
87
+ # curl http://demo.openapply.com/api/v1/students/95?auth_token=demo_site_api_key
88
+ # * +options+ - see httparty options [http://www.rubydoc.info/github/jnunemaker/httparty]
89
+ def oa_api_call(url, options={})
90
+ self.class.get(url, options)
91
+ end
92
+
93
+ # Does checks the info for validity & unpacks the json retubed to a JS formatt
94
+ #
95
+ # ==== Attributes
96
+ # * +url+ - this is the url to do the call
97
+ # /api/v1/students/95?auth_token=demo_site_api_key
98
+ # is the url passed when wanting to do the following cli api call
99
+ # curl http://demo.openapply.com/api/v1/students/95?auth_token=demo_site_api_key
100
+ # * +options+ - see httparty options [http://www.rubydoc.info/github/jnunemaker/httparty]
101
+ def oa_answer(url, options={})
102
+ # puts
103
+ # puts "GIVEN URL: #{ url.inspect }"
104
+ return { error: 'no url given' } if url.nil? or url.to_s.eql? ""
105
+ return { error: 'bad url - has space' } if url.include? " "
106
+ return { error: 'bad api_path' } unless url.include? "#{api_path}"
107
+ return { error: 'bad auth_token' } unless url.include? "auth_token=#{api_key}"
108
+ api_answer = nil
109
+
110
+ handle_timeouts do
111
+ api_answer = oa_api_call(url, options)
112
+ end
113
+
114
+ # puts "API ANSWER: #{api_answer}"
115
+ # puts "API ANSWER: #{api_answer.inspect}"
116
+ return { error: 'no response' } unless api_answer.respond_to? "response"
117
+ return { error: 'no response' } if api_answer.response.nil?
118
+ return { error: 'no response' } if api_answer.response.to_s.eql? ""
119
+ return JSON.parse(api_answer.response.body, symbolize_names: true)
120
+ end
121
+ # alias_method :openapply_answer, :oa_answer
122
+
123
+ end # Client
124
+
125
+ end # Openapply
data/openapply.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "openapply/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "openapply"
8
+ spec.version = Openapply::VERSION
9
+ spec.authors = ["Bill Tihen"]
10
+ spec.email = ["btihen@gmail.com"]
11
+
12
+ spec.summary = %q{Access OpenApply's API with Ruby}
13
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
14
+ spec.homepage = "https://github.com/btihen/openapply"
15
+ spec.license = "MIT"
16
+
17
+ # # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "http://rubygems.org"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against " \
23
+ # "public gem pushes."
24
+ # end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ f.match(%r{^(test|spec|features)/})
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_dependency "httparty", "~> 0.15"
34
+ spec.add_dependency "json" , "~> 2.1"
35
+
36
+ spec.add_development_dependency "webmock" , "~> 3.1"
37
+ spec.add_development_dependency "bundler", "~> 1.15"
38
+ spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_development_dependency "rspec", "~> 3.7"
40
+ # spec.add_development_dependency "rspec", "~> 3.0"
41
+ spec.add_development_dependency "simplecov", "~> 0.15"
42
+ # spec.add_development_dependency "rspec-nc", "~> 3.0"
43
+ # spec.add_development_dependency "guard", "~> 2.14"
44
+ # spec.add_development_dependency "guard-rspec", "~> 4.7"
45
+ # spec.add_development_dependency "pry", "~> 0.11"
46
+ # spec.add_development_dependency "pry-remote", "~> 0.1"
47
+ # spec.add_development_dependency "pry-nav", "~> 0.2"
48
+ end