nasturtium 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/README.md ADDED
@@ -0,0 +1,534 @@
1
+ # Nasturtium
2
+
3
+ ![Nasturtium Logo](https://github.com/SpeciesFileGroup/nasturtium/assets/8573609/7a19d255-a62e-429d-9fa0-43711ad60f2c)
4
+
5
+ This is a Ruby wrapper on the [iNaturalist](https://api.inaturalist.org/v1/docs/#!/Search/get_search) API. Code follow the spirit/approach of the Gem [serrano](https://github.com/sckott/serrano), and indeed much of the wrapping utility is copied 1:1 from that repo, thanks [@sckott](https://github.com/sckott).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'nasturtium'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install nasturtium
22
+
23
+ ## Usage
24
+
25
+ ### Controlled vocabulary terms
26
+
27
+ Get controlled vocabulary terms
28
+ ```ruby
29
+ Nasturtium.controlled_terms # => MultiJson object
30
+ ```
31
+
32
+ Get controlled vocabulary terms for a taxon
33
+ ```ruby
34
+ Nasturtium.controlled_terms(taxon_id: 1) # => MultiJson object
35
+ ```
36
+
37
+ ### Identifications
38
+ These are just some examples. For a complete list [view the tests](https://github.com/SpeciesFileGroup/nasturtium/blob/main/test/identifications_test.rb) for examples or the [API documentation](https://api.inaturalist.org/v1/docs/#!/Identifications/get_identifications).
39
+
40
+ Get an identification by ID
41
+ ```ruby
42
+ Nasturtium.identifications(id: 342040114) # => MultiJson object
43
+ ```
44
+
45
+ Get identifications in which the taxon is the same as the observation's taxon
46
+ ```ruby
47
+ Nasturtium.identifications(current_taxon: true) # => MultiJson object
48
+ ```
49
+
50
+ Get identifications which were added by the observer
51
+ ```ruby
52
+ Nasturtium.identifications(own_observation: true) # => MultiJson object
53
+ ```
54
+
55
+ Get identifications by taxonomic rank
56
+ ```ruby
57
+ Nasturtium.identifications(rank: 'suborder') # => MultiJson object
58
+ ```
59
+
60
+ Get identifications with the rank species and the observation rank variety:
61
+ ```ruby
62
+ Nasturtium.identifications(rank: 'species', observation_rank: 'variety') # => MultiJson object
63
+ ```
64
+
65
+ Get identifications by a user_id:
66
+ ```ruby
67
+ Nasturtium.identifications(user_id: '20717') # => MultiJson object
68
+ ```
69
+
70
+ Get identifications by category:
71
+ ```ruby
72
+ Nasturtium.identifications(category: 'improving') # => MultiJson object
73
+ ```
74
+
75
+ Get identifications by quality grade:
76
+ ```ruby
77
+ Nasturtium.identifications(quality_grade: 'research') # => MultiJson object
78
+ ```
79
+
80
+ Get identifications by taxon_id:
81
+ ```ruby
82
+ Nasturtium.identifications(taxon_id: 42196) # => MultiJson object
83
+ ```
84
+
85
+ ---
86
+ ### Mapping
87
+ Get a grid map tile for the turkey vulture at zoom level 2 for coordinates (0, 1):
88
+ ```ruby
89
+ Nasturtium.mapping('grid', 2, 0, 1, style: 'geotilegrid', tile_size: 512, taxon_id: 4756)
90
+ ```
91
+
92
+ Get a colored_heatmap map tile for the turkey vulture at zoom level 2 for coordinates (0, 1):
93
+ ```ruby
94
+ Nasturtium.mapping('colored_heatmap', 2, 0, 1, tile_size: 512, taxon_id: 4756, color: '#00ff00')
95
+ ```
96
+
97
+ Get a points map tile for the turkey vulture at zoom level 2 for coordinates (0, 0):
98
+ ```ruby
99
+ Nasturtium.mapping('points', 2, 0, 0, tile_size: 512, taxon_id: 4756, color: '#00ff00')
100
+ ```
101
+
102
+ Get a points map tile for the turkey vulture at zoom level 2 for coordinates (0, 0):
103
+ ```ruby
104
+ Nasturtium.mapping('grid', 2, 0, 1, taxon_id: 4756, return_json: true)
105
+ ```
106
+
107
+ Get the taxon_places map for turkey vultures:
108
+ ```ruby
109
+ Nasturtium.mapping('taxon_places', 2, 0, 1, taxon_id: 4756)
110
+ ```
111
+
112
+ Get the taxon_ranges map for turkey vultures:
113
+ ```ruby
114
+ Nasturtium.mapping('taxon_ranges', 2, 0, 1, taxon_id: 4756)
115
+ ```
116
+
117
+ Get the places map for turkey vultures in place 35:
118
+ ```ruby
119
+ Nasturtium.mapping('places', 2, 0, 0, place_id: 35, taxon_id: 4756, tile_size: 512)
120
+ ```
121
+
122
+
123
+ ---
124
+ ### Observations
125
+ These are just some examples. For a complete list [view the tests](https://github.com/SpeciesFileGroup/nasturtium/blob/main/test/observations_test.rb) for examples or the [API documentation](https://api.inaturalist.org/v1/docs/#!/Observations/get_observations).
126
+
127
+ Get an observation by ID
128
+ ```ruby
129
+ Nasturtium.observations(id: '150842485') # => MultiJson object
130
+ ```
131
+
132
+ Get observations with positional accuracy/coordinate uncertainty specified
133
+ ```ruby
134
+ Nasturtium.observations(acc: true) # => MultiJson object
135
+ ```
136
+
137
+ Get captive/cultivated observations
138
+ ```ruby
139
+ Nasturtium.observations(captive: true) # => MultiJson object
140
+ ```
141
+
142
+ Exclude captive/cultivated observations
143
+ ```ruby
144
+ Nasturtium.observations(captive: false) # => MultiJson object
145
+ ```
146
+
147
+ Get observations in which the taxon is endemic to their location
148
+ ```ruby
149
+ Nasturtium.observations(endemic: true) # => MultiJson object
150
+ ```
151
+
152
+ Get observations that are georeferenced
153
+ ```ruby
154
+ Nasturtium.observations(geo: true) # => MultiJson object
155
+ ```
156
+
157
+ Get observations that have been identified
158
+ ```ruby
159
+ Nasturtium.observations(identified: true) # => MultiJson object
160
+ ```
161
+
162
+ Get observations in which the taxon has been introduced in their location
163
+ ```ruby
164
+ Nasturtium.observations(introduced: true) # => MultiJson object
165
+ ```
166
+
167
+ Get observations that show on map tiles
168
+ ```ruby
169
+ Nasturtium.observations(mappable: true) # => MultiJson object
170
+ ```
171
+
172
+ Get observations in which the taxon is native in their location
173
+ ```ruby
174
+ Nasturtium.observations(native: true) # => MultiJson object
175
+ ```
176
+
177
+ Get observations in which the taxon was observed outside of their known range
178
+ ```ruby
179
+ Nasturtium.observations(out_of_range: true) # => MultiJson object
180
+ ```
181
+
182
+ Get observations with photos
183
+ ```ruby
184
+ Nasturtium.observations(photos: true) # => MultiJson object
185
+ ```
186
+
187
+ Get observations that have been favorited by at least 1 user
188
+ ```ruby
189
+ Nasturtium.observations(popular: true) # => MultiJson object
190
+ ```
191
+
192
+ Get observations with sounds
193
+ ```ruby
194
+ Nasturtium.observations(sounds: true) # => MultiJson object
195
+ ```
196
+
197
+ Get observations in which the taxon concept is active
198
+ ```ruby
199
+ Nasturtium.observations(taxon_is_active: true) # => MultiJson object
200
+ ```
201
+
202
+ Get observations in which the taxon is threatened in their location
203
+ ```ruby
204
+ Nasturtium.observations(threatened: true) # => MultiJson object
205
+ ```
206
+
207
+ Get observations with a quality_grade of needs_id or research
208
+ ```ruby
209
+ Nasturtium.observations(verifiable: true) # => MultiJson object
210
+ ```
211
+
212
+ Get observations that have a cc0 license
213
+ ```ruby
214
+ Nasturtium.observations(license: 'cc0') # => MultiJson object
215
+ ```
216
+
217
+ Get observations that have a license
218
+ ```ruby
219
+ Nasturtium.observations(licensed: true) # => MultiJson object
220
+ ```
221
+
222
+ Get observations that have a cc0 photo license
223
+ ```ruby
224
+ Nasturtium.observations(photo_license: 'cc0') # => MultiJson object
225
+ ```
226
+
227
+ Get observations in which at least 1 photo has a license
228
+ ```ruby
229
+ Nasturtium.observations(photo_licensed: true) # => MultiJson object
230
+ ```
231
+
232
+ Get observations by a place_id
233
+ ```ruby
234
+ Nasturtium.observations(place_id: 26) # => MultiJson object
235
+ ```
236
+
237
+ Get observations from a project_id
238
+ ```ruby
239
+ Nasturtium.observations(project_id: 22499) # => MultiJson object
240
+ ```
241
+
242
+ Get observations by a taxonomic rank
243
+ ```ruby
244
+ Nasturtium.observations(rank: 'subspecies') # => MultiJson object
245
+ ```
246
+
247
+ Get observations by an iNaturalist network website site_id
248
+ ```ruby
249
+ Nasturtium.observations(site_id: 2) # => MultiJson object
250
+ ```
251
+
252
+ Get observations with a cc0 licensed sound recording
253
+ ```ruby
254
+ Nasturtium.observations(sound_license: 'cc0') # => MultiJson object
255
+ ```
256
+
257
+ Get observations by a taxon_id
258
+ ```ruby
259
+ Nasturtium.observations(taxon_id: '522193') # => MultiJson object
260
+ ```
261
+
262
+ Get observations by a taxon_name
263
+ ```ruby
264
+ Nasturtium.observations(taxon_name: 'Nasturtium floridanum') # => MultiJson object
265
+ ```
266
+
267
+ Get observations by a user_id
268
+ ```ruby
269
+ Nasturtium.observations(user_id: '20717') # => MultiJson object
270
+ ```
271
+
272
+ Get observations by a user_login
273
+ ```ruby
274
+ Nasturtium.observations(user_login: 'debpaul') # => MultiJson object
275
+ ```
276
+
277
+ Get observations by a date
278
+ ```ruby
279
+ Nasturtium.observations(year: 2020, month: 3, day: 15) # => MultiJson object
280
+ ```
281
+
282
+ Get observations that have a controlled vocabulary term
283
+ ```ruby
284
+ Nasturtium.observations(term_id: 1) # => MultiJson object
285
+ ```
286
+
287
+ Get observations that have controlled vocabulary term 1 and controlled vocabulary value 2
288
+ ```ruby
289
+ Nasturtium.observations(term_id: 1, term_value_id: 2)
290
+ ```
291
+
292
+ Get observations with positional accuracy above 100 meters and below 200 meters
293
+ ```ruby
294
+ Nasturtium.observations(acc_above: 100, acc_below: 200)
295
+ ```
296
+
297
+ Get observations with open geoprivacy
298
+ ```ruby
299
+ Nasturtium.observations(geoprivacy: 'open')
300
+ ```
301
+
302
+ Get observations with a taxonomic rank above genus and below phylum
303
+ ```ruby
304
+ Nasturtium.observations(rank_highest: 'genus', rank_lowest: 'phylum')
305
+ ```
306
+
307
+ Get observations in which most people agree on the identification
308
+ ```ruby
309
+ Nasturtium.observations(identifications: 'most_agree')
310
+ ```
311
+
312
+ Get observations with research quality grade identifications
313
+ ```ruby
314
+ Nasturtium.observations(quality_grade: 'research')
315
+ ```
316
+
317
+ Get observations within a 1 km radius of 45.703259, -85.552406
318
+ ```ruby
319
+ @ne_lat = 40.084300
320
+ @sw_lat = 40.075877
321
+ @ne_lng = -88.198636
322
+ @sw_lng = -88.210169
323
+ Nasturtium.observations(latitude: 45.703259, longitude: -85.552406, radius: 1)
324
+ ```
325
+
326
+ Get observations within a bounding box
327
+ ```ruby
328
+ @ne_lat = 40.084300
329
+ @sw_lat = 40.075877
330
+ @ne_lng = -88.198636
331
+ @sw_lng = -88.210169
332
+ Nasturtium.observations(ne_latitude: @ne_lat, ne_longitude: @ne_lng, sw_longitude: @sw_lat, sw_latitude: @sw_lng)
333
+ ```
334
+
335
+ Search for observations with the query Parastratiosphecomyia
336
+ ```ruby
337
+ Nasturtium.observations(q: 'Parastratiosphecomyia')
338
+ ```
339
+
340
+ Search for observations with Meadowbrook in a place name
341
+ ```ruby
342
+ Nasturtium.observations(q: 'Meadowbrook', search_on: 'place')
343
+ ```
344
+
345
+ Search for observations with blue in a tag name
346
+ ```ruby
347
+ Nasturtium.observations(q: 'blue', search_on: 'tags')
348
+ ```
349
+
350
+ Search for observations with blue in the description
351
+ ```ruby
352
+ Nasturtium.observations(q: 'blue', search_on: 'description')
353
+ ```
354
+
355
+ Search for observations with grizzly in the names
356
+ ```ruby
357
+ Nasturtium.observations(q: 'grizzly', search_on: 'names')
358
+ ```
359
+
360
+ ---
361
+ ### Places
362
+ Get places by ID with an admin_level of 100
363
+ ```ruby
364
+ Nasturtium.places_id(1000, admin_level: 100) # => MultiJson object
365
+ ```
366
+
367
+ ---
368
+ ### Places autocomplete
369
+ Get suggested place name autocompletions
370
+ ```ruby
371
+ Nasturtium.places_autocomplete('Kickapoo Rail Trail') # => MultiJson object
372
+ ```
373
+
374
+ ---
375
+ ### Places nearby
376
+ Get place names nearby within a bounding box and that include the string Meadowbrook
377
+ ```ruby
378
+ @ne_lat = 40.084300
379
+ @sw_lat = 40.075877
380
+ @ne_lng = -88.198636
381
+ @sw_lng = -88.210169
382
+ Nasturtium.places_nearby(@ne_lat, @ne_lng, @sw_lat, @sw_lng, name: "Meadowbrook") # => MultiJson object
383
+ ```
384
+
385
+ ---
386
+ ### Posts
387
+ Get journal posts:
388
+ ```ruby
389
+ Nasturtium.posts # => MultiJson object
390
+ ```
391
+
392
+ Get journal posts for parent_id:
393
+ ```ruby
394
+ Nasturtium.posts(parent_id: 1, page: 1, per_page: 10) # => MultiJson object
395
+ ```
396
+
397
+ Get journal posts for project_id:
398
+ ```ruby
399
+ Nasturtium.posts(project_id: 42768) # => MultiJson object
400
+ ```
401
+
402
+ Get journal posts for a user:
403
+ ```ruby
404
+ Nasturtium.posts(login: 'loarie') # => MultiJson object
405
+ ```
406
+
407
+ ---
408
+ ### Projects
409
+ Search projects with query term, Illinois:
410
+ ```ruby
411
+ Nasturtium.projects(q: 'Illinois') # => MultiJson object
412
+ ```
413
+
414
+ Get a project by ID
415
+ ```ruby
416
+ Nasturtium.projects(id: 22499) # => MultiJson object
417
+ ```
418
+
419
+ Search for projects within 5 km of 40.11136254505831, -88.2460817474295
420
+ ```ruby
421
+ Nasturtium.projects(latitude: 40.11136254505831, longitude: -88.2460817474295, radius: 5) # => MultiJson object
422
+ ```
423
+
424
+ Get projects with place_id or with place_id as a place ancestor
425
+ ```ruby
426
+ Nasturtium.projects(place_id: 35) # => MultiJson object
427
+ ```
428
+
429
+ Get featured projects on iNaturalist México
430
+ ```ruby
431
+ Nasturtium.projects(featured: true, site_id: 2) # => MultiJson object
432
+ ```
433
+
434
+ Get noteworthy projects on iNaturalist
435
+ ```ruby
436
+ Nasturtium.projects(noteworthy: true, site_id: 1) # => MultiJson object
437
+ ```
438
+
439
+ Get projects that include user_id as a member
440
+ ```ruby
441
+ Nasturtium.projects(member_id: 477) # => MultiJson object
442
+ ```
443
+
444
+ Get projects with journal posts
445
+ ```ruby
446
+ Nasturtium.projects(has_posts: true) # => MultiJson object
447
+ ```
448
+
449
+ ---
450
+ ### Project members
451
+ Get the members of project_id 733
452
+ ```ruby
453
+ Nasturtium.project_members(733, page: 1, per_page: 10)
454
+ ```
455
+
456
+ ---
457
+ ### Search
458
+ Search places, projects, taxa, or users:
459
+ ```ruby
460
+ Nasturtium.search(q: 'Quercus', sources: 'taxa') # => MultiJson object
461
+ ```
462
+
463
+ ---
464
+ ### Taxa
465
+ Search and fetch taxa with a comma-separted list of IDs:
466
+ ```ruby
467
+ Nasturtium.taxa(id: '1,2') # => MultiJson object
468
+ ```
469
+ Search and fetch taxa:
470
+ ```ruby
471
+ Nasturtium.taxa(q: 'Danaus plexippus', rank: 'species') # => MultiJson object
472
+ ```
473
+ Fetch taxa ordered by greatest observations count:
474
+ ```ruby
475
+ Nasturtium.taxa(rank: 'species', order: 'desc', order_by: 'observations_count') # => MultiJson object
476
+ ```
477
+
478
+ ---
479
+ ### Taxa autocomplete
480
+ Get suggested taxa names for a query Sinapis at ranks genus,species,subspecies with a limit of 5 suggestions:
481
+ ```ruby
482
+ Nasturtium.taxa_autocomplete(q: 'Sinapis', rank: 'genus,species,subspecies', per_page: 5) # => MultiJson object
483
+ ```
484
+ Include all names for each suggested taxon:
485
+ ```ruby
486
+ Nasturtium.taxa_autocomplete(q: 'Sinapis', rank: 'genus,species,subspecies', per_page: 5, all_names: true) # => MultiJson object
487
+ ```
488
+ Get common names by the language at preferred_place_id which adds a preferred_common_name key (use Nasturtium.places_autocomplete to lookup place_id's):
489
+ ```ruby
490
+ Nasturtium.taxa_autocomplete(q: 'Danaus plexippus', preferred_place_id: 6903, rank: 'species') # => MultiJson object
491
+ ```
492
+
493
+ ---
494
+ ### User
495
+ Get a user by ID
496
+ ```ruby
497
+ Nasturtium.user(20717) # => MultiJson object
498
+ ```
499
+
500
+
501
+ ---
502
+ ### User autocomplete
503
+ Suggest a user by autocomplete
504
+ ```ruby
505
+ Nasturtium.user_autocomplete('debpau') # => MultiJson object
506
+ ```
507
+
508
+
509
+ ---
510
+ ### User projects
511
+ Get a user's projects of type collection
512
+ ```ruby
513
+ Nasturtium.user_projects(20717, project_type: 'collection') # => MultiJson object
514
+ ```
515
+ ---
516
+
517
+
518
+ ## Development
519
+
520
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
521
+
522
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
523
+
524
+ ## Contributing
525
+
526
+ Bug reports and pull requests are welcome on GitHub at https://github.com/SpeciesFileGroup/nasturtium. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/SpeciesFileGroup/nasturtium/blob/main/CODE_OF_CONDUCT.md).
527
+
528
+ ## License
529
+
530
+ The gem is available as open source under the terms of the [NCSA/Illinois](https://opensource.org/licenses/NCSA).
531
+
532
+ ## Code of Conduct
533
+
534
+ Everyone interacting in the Nasturtium project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/SpeciesFileGroup/nasturtium/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ t.verbose = true
11
+ end
12
+
13
+ desc "Run tests"
14
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "nasturtium"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nasturtium
4
+ # Custom error class for rescuing from all Bonamia errors
5
+ class Error < StandardError; end
6
+
7
+ # Raised when Bionomia returns the HTTP status code 400
8
+ class BadRequest < Error; end
9
+
10
+ # Raised when Bionomia returns the HTTP status code 404
11
+ class NotFound < Error; end
12
+
13
+ # Raised when Bionomia returns the HTTP status code 500
14
+ class InternalServerError < Error; end
15
+
16
+ # Raised when Bionomia returns the HTTP status code 502
17
+ class BadGateway < Error; end
18
+
19
+ # Raised when Bionomia returns the HTTP status code 503
20
+ class ServiceUnavailable < Error; end
21
+
22
+ # Raised when Bionomia returns the HTTP status code 504
23
+ class GatewayTimeout < Error; end
24
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "multi_json"
5
+
6
+ # @private
7
+ module Faraday
8
+ module NasturtiumErrors
9
+ # @private
10
+ class Middleware < Faraday::Middleware
11
+ def call(env)
12
+ @app.call(env).on_complete do |response|
13
+ case response[:status].to_i
14
+ when 400
15
+ raise Nasturtium::BadRequest, error_message_400(response)
16
+ when 404
17
+ raise Nasturtium::NotFound, error_message_400(response)
18
+ when 500
19
+ raise Nasturtium::InternalServerError, error_message_500(response, "Something is technically wrong.")
20
+ when 502
21
+ raise Nasturtium::BadGateway, error_message_500(response, "The server returned an invalid or incomplete response.")
22
+ when 503
23
+ raise Nasturtium::ServiceUnavailable, error_message_500(response, "Crossref is rate limiting your requests.")
24
+ when 504
25
+ raise Nasturtium::GatewayTimeout, error_message_500(response, "504 Gateway Time-out")
26
+ end
27
+ end
28
+ end
29
+
30
+
31
+ def initialize(app)
32
+ super app
33
+ @parser = nil
34
+ end
35
+
36
+ private
37
+
38
+ def error_message_400(response)
39
+ "\n #{response[:method].to_s.upcase} #{response[:url]}\n Status #{response[:status]}#{error_body(response[:body])}"
40
+ end
41
+
42
+ def error_body(body)
43
+ if !body.nil? && !body.empty? && body.is_a?(String)
44
+ if json?(body)
45
+ body = ::MultiJson.load(body)
46
+ if body["message"].nil?
47
+ body = nil
48
+ elseif body["message"].length == 1
49
+ body = body["message"]
50
+ else
51
+ body = body["message"].collect { |x| x["message"] }.join("; ")
52
+ end
53
+ end
54
+ end
55
+
56
+ if body.nil?
57
+ nil
58
+ else
59
+ ": #{body}"
60
+ end
61
+ end
62
+
63
+ def error_message_500(response, body = nil)
64
+ "#{response[:method].to_s.upcase} #{response[:url]}: #{[response[:status].to_s + ":", body].compact.join(" ")}"
65
+ end
66
+
67
+ def json?(string)
68
+ MultiJson.load(string)
69
+ true
70
+ rescue MultiJson::ParseError
71
+ false
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,26 @@
1
+ # taken from https://raw.githubusercontent.com/sckott/serrano/main/lib/serrano/helpers/configuration.rb
2
+ # taken from: https://viget.com/extend/easy-gem-configuration-variables-with-defaults
3
+ module Configuration
4
+ def configuration
5
+ yield self
6
+ end
7
+
8
+ def define_setting(name, default = nil)
9
+ class_variable_set("@@#{name}", default)
10
+ define_class_method "#{name}=" do |value|
11
+ class_variable_set("@@#{name}", value)
12
+ end
13
+ define_class_method name do
14
+ class_variable_get("@@#{name}")
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def define_class_method(name, &block)
21
+ (class << self; self; end).instance_eval do
22
+ define_method name, &block
23
+ end
24
+ end
25
+ end
26
+