ecoportal-api 0.9.8 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +1,14 @@
1
1
  module Ecoportal
2
2
  module API
3
3
  class V1
4
- # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
4
+ # @attr_reader client [Common::Client] a `Common::Client` object that
5
+ # holds the configuration of the api connection.
5
6
  class People
6
7
  extend Common::BaseClass
7
- include Enumerable
8
8
  include Common::DocHelpers
9
+ include Enumerable
9
10
 
10
- JOB_TIMEOUT = 240
11
+ JOB_TIMEOUT = 240
11
12
  DELAY_STATUS_CHECK = 5
12
13
 
13
14
  class_resolver :person_class, "Ecoportal::API::V1::Person"
@@ -30,35 +31,49 @@ module Ecoportal
30
31
  # @param silent [Boolean] `false` to show percentage of progress.
31
32
  # @yield [person] does some stuff with the person.
32
33
  # @yieldparam person [Person]
33
- def each(params: {}, silent: false, &block)
34
- return to_enum(:each, params: params, silent: silent) unless block
35
- cursor_id = nil; results = 0
34
+ def each(params: {}, silent: false) # rubocop:disable Metrics/AbcSize
35
+ return to_enum(:each, params: params, silent: silent) unless block_given?
36
+
37
+ cursor_id = nil
38
+ results = 0
39
+
36
40
  puts "\n" unless silent
41
+
37
42
  loop do
38
43
  params.update(cursor_id: cursor_id) if cursor_id
39
- body = nil; response = nil; count = 5
44
+
45
+ body = nil
46
+ response = nil
47
+ count = 5
48
+
40
49
  loop do
41
50
  response = client.get("/people", params: params)
42
51
  body = response && body_data(response.body)
43
52
  break if response.success? || count <= 0
53
+
44
54
  puts "Request failed - Status #{response.status}: #{body}"
45
55
  count -= 1
56
+
46
57
  sleep(0.5)
47
58
  end
59
+
48
60
  raise "Request failed - Status #{response.status}: #{body}" unless response.success?
49
61
 
50
- unless silent || (total = body["total_results"]) == 0
62
+ unless silent || (total = body["total_results"])&.zero?
51
63
  results += body["results"].length
52
64
  percent = results * 100 / total
65
+
53
66
  msg = "People GET"
54
- msg += " (search=#{params[:q]})" if params.key?(:q)
55
- print "#{msg}: #{percent.round}% (of #{total})\r"
67
+ msg << " (search=#{params[:q]})" if params.key?(:q)
68
+
69
+ print "#{msg}: #{percent.round}% (of #{total}): #{results}\r"
56
70
  $stdout.flush
57
71
  end
58
72
 
59
73
  body["results"].each do |person|
60
74
  yield person_class.new(person)
61
75
  end
76
+
62
77
  break unless (cursor_id = body["cursor_id"])
63
78
  end
64
79
  self
@@ -81,9 +96,10 @@ module Ecoportal
81
96
  # @return [Person] the person with `id` (internal or external) contained in `doc`.
82
97
  def get(doc)
83
98
  id = get_id(doc)
84
- response = client.get("/people/"+CGI.escape(id))
99
+ response = client.get("/people/#{CGI.escape(id)}")
85
100
  body = body_data(response.body)
86
101
  return person_class.new(body) if response.success?
102
+
87
103
  raise "Could not get person #{id} - Error #{response.status}: #{body}"
88
104
  end
89
105
 
@@ -93,7 +109,7 @@ module Ecoportal
93
109
  def update(doc)
94
110
  body = get_body(doc)
95
111
  id = get_id(doc)
96
- client.patch("/people/"+CGI.escape(id), data: body)
112
+ client.patch("/people/#{CGI.escape(id)}", data: body)
97
113
  end
98
114
 
99
115
  # Requests to create a person via api.
@@ -110,7 +126,7 @@ module Ecoportal
110
126
  def upsert(doc)
111
127
  body = get_body(doc)
112
128
  id = get_id(doc)
113
- client.post("/people/"+CGI.escape(id), data: body)
129
+ client.post("/people/#{CGI.escape(id)}", data: body)
114
130
  end
115
131
 
116
132
  # Requests to completelly remove from an organization an existing person via api.
@@ -118,7 +134,7 @@ module Ecoportal
118
134
  # @return [Response] an object with the api response.
119
135
  def delete(doc)
120
136
  id = get_id(doc)
121
- client.delete("/people/"+CGI.escape(id))
137
+ client.delete("/people/#{CGI.escape(id)}")
122
138
  end
123
139
 
124
140
  # Creates a `BatchOperation` and yields it to the given bock.
@@ -128,8 +144,15 @@ module Ecoportal
128
144
  # @return [Ecoportal::API::Common::Response] the results of the batch
129
145
  def batch(job_mode: true, &block)
130
146
  return job(&block) if job_mode
131
- operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
147
+
148
+ operation = Common::BatchOperation.new(
149
+ "/people",
150
+ person_class,
151
+ logger: client.logger
152
+ )
153
+
132
154
  yield operation
155
+
133
156
  # The batch operation is responsible for logging the output
134
157
  client.post("/people/batch", data: operation.as_json).tap do |response|
135
158
  operation.process_response(response)
@@ -138,16 +161,25 @@ module Ecoportal
138
161
 
139
162
  # @return [Ecoportal::API::Common::Response] the results of the batch job
140
163
  def job
141
- operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
164
+ operation = Common::BatchOperation.new(
165
+ "/people",
166
+ person_class,
167
+ logger: client.logger
168
+ )
169
+
142
170
  yield operation
171
+
143
172
  job_id = create_job(operation)
144
173
  status = wait_for_job_completion(job_id)
145
174
 
146
175
  if status&.complete?
147
176
  job_result(job_id, operation)
148
177
  else
149
- msg = "Job `#{job_id}` not complete. Probably timeout after #{JOB_TIMEOUT} seconds. Current status: #{status}"
150
- raise API::Errors::TimeOut.new msg
178
+ msg = "Job `#{job_id}` not complete. "
179
+ msg << "Probably timeout after #{JOB_TIMEOUT} seconds. "
180
+ msg << "Current status: #{status}"
181
+
182
+ raise API::Errors::TimeOut, msg
151
183
  end
152
184
  end
153
185
 
@@ -160,10 +192,15 @@ module Ecoportal
160
192
  private
161
193
 
162
194
  JobStatus = Struct.new(:id, :complete?, :errored?, :progress)
195
+
163
196
  def job_status(job_id)
164
197
  response = client.get("/people/job/#{CGI.escape(job_id)}/status")
165
198
  body = response && body_data(response.body)
166
- raise "Status error (#{response.status}) - Errors: #{body}" unless response.success?
199
+
200
+ msg = "Status error (#{response.status}) - "
201
+ msg << "Errors: #{body}"
202
+ raise msg unless response.success?
203
+
167
204
  JobStatus.new(
168
205
  body["id"],
169
206
  body["complete"],
@@ -183,10 +220,12 @@ module Ecoportal
183
220
  # timeout library is evil. So we make poor-man timeout.
184
221
  # https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
185
222
  before = Time.now
186
- while true
223
+
224
+ loop do
187
225
  status = job_status(job_id)
188
226
  break status if status.complete?
189
227
  break status if Time.now >= before + JOB_TIMEOUT
228
+
190
229
  sleep(DELAY_STATUS_CHECK)
191
230
  status
192
231
  end
@@ -207,7 +246,6 @@ module Ecoportal
207
246
  def body_data(body)
208
247
  body
209
248
  end
210
-
211
249
  end
212
250
  end
213
251
  end
@@ -9,14 +9,16 @@ module Ecoportal
9
9
  # @attr details [PersonDetails, nil] the details of the person or `nil` if missing.
10
10
  class Person < Common::BaseModel
11
11
  passthrough :id, :external_id, :name, :email, :filter_tags
12
+ passthrough :archived
12
13
  passthrough :supervisor_id, :contractor_organization_id
14
+ passthrough :brand_id
13
15
  passthrough :freemium
14
16
 
15
17
  class_resolver :person_schema_class, "Ecoportal::API::V1::PersonSchema"
16
18
  class_resolver :person_details_class, "Ecoportal::API::V1::PersonDetails"
17
19
  embeds_one :details, nullable: true, klass: :person_details_class
18
20
 
19
- VALID_TAG_REGEX = /^[A-Za-z0-9 &_'\/.-]+$/
21
+ VALID_TAG_REGEX = /^[A-Za-z0-9 &_'\/.-]+$/
20
22
  VALID_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/
21
23
 
22
24
  # Gets the supervisor (`Person`) of this person, with given his `supervisor_id`.
@@ -47,9 +49,8 @@ module Ecoportal
47
49
  # Sets the email of a person.
48
50
  # @param value [String, nil] the email of this person.
49
51
  def email=(value)
50
- unless !value || value.match(VALID_EMAIL_REGEX)
51
- raise "Invalid email #{value.inspect}"
52
- end
52
+ raise "Invalid email #{value.inspect}" if value && !value.match(VALID_EMAIL_REGEX)
53
+
53
54
  doc["email"] = value&.downcase
54
55
  end
55
56
 
@@ -58,15 +59,16 @@ module Ecoportal
58
59
  # @raise [Exception] if there was any invalid string tag.
59
60
  # @param value [Array<String>] array of tags.
60
61
  def filter_tags=(value)
61
- unless value.is_a?(Array)
62
- raise "filter_tags= needs to be passed an Array, got #{value.class}"
63
- end
62
+ msg = "filter_tags= needs to be passed an Array, got #{value.class}"
63
+ raise ArgumentError, msg unless value.is_a?(Array)
64
+
64
65
  end_tags = value.compact.map do |tag|
65
- unless tag.match(VALID_TAG_REGEX)
66
- raise "Invalid filter tag #{tag.inspect}"
67
- end
66
+ msg = "Invalid filter tag #{tag.inspect}"
67
+ raise ArgumentError, msg unless tag.match(VALID_TAG_REGEX)
68
+
68
69
  tag.upcase
69
70
  end
71
+
70
72
  set_uniq_array_keep_order("filter_tags", end_tags)
71
73
  end
72
74
 
@@ -105,8 +107,10 @@ module Ecoportal
105
107
  end
106
108
 
107
109
  # Sets the PersonDetails to the person, depending on the parameter received:
108
- # - `PersonSchema`: initializes the `PersonDetails` as per the schema specified (`schema_id` and `fields`).
109
- # - `String`: it just sets the `schema_id` on the `PersonDetails` (as `fields` is not include, `details[key]=` will throw error).
110
+ # - `PersonSchema`: initializes the `PersonDetails` as per the schema specified
111
+ # (`schema_id` and `fields`).
112
+ # - `String`: it just sets the `schema_id` on the `PersonDetails`
113
+ # (as `fields` is not include, `details[key]=` will throw error).
110
114
  # (see #details=)
111
115
  # @note
112
116
  # - this method alone only sets the internal structure of the details.
@@ -130,7 +134,6 @@ module Ecoportal
130
134
  }
131
135
  end
132
136
  end
133
-
134
137
  end
135
138
  end
136
139
  end
@@ -40,7 +40,8 @@ module Ecoportal
40
40
 
41
41
  # Gets the value of one specific field of the PersonDetails.
42
42
  # @param id [String] the `id` or the `alt_id` of the target field.
43
- # @return [String, Array<String>, Boolean, Array<Boolean>, Date, Array<Date>, Numberic, Array<Numeric>] the value of field or `nil` if missing.
43
+ # @return [String, Array<String>, Boolean, Array<Boolean>, Date, Array<Date>, Numberic, Array<Numeric>]
44
+ # the value of field or `nil` if missing.
44
45
  def [](id)
45
46
  get_field(id)&.value
46
47
  end
@@ -50,11 +51,10 @@ module Ecoportal
50
51
  # @param id [String] the `id` or the `alt_id` of the target field.
51
52
  # @return [void]
52
53
  def []=(id, value)
53
- if field = get_field(id)
54
- field.value = value
55
- else
56
- raise MissingId.new("details[#{id.inspect}] is missing. Did you forget to load the schema?")
57
- end
54
+ msg = "details[#{id.inspect}] is missing. Did you forget to load the schema?"
55
+ raise MissingId, msg unless (field = get_field(id))
56
+
57
+ field.value = value
58
58
  end
59
59
 
60
60
  # Checks if an `id` or `alt_id` exists
@@ -67,12 +67,14 @@ module Ecoportal
67
67
 
68
68
  # @return [Boolean] `true` if `id` exists and `value` has changed, `false` otherwise
69
69
  def changed?(id, doc = :original)
70
- return false unless field = get_field(id)
70
+ return false unless (field = get_field(id))
71
+
71
72
  field.as_update.key?("value")
72
73
  end
73
74
 
74
75
  def original_value(id)
75
- return nil unless field = get_field(id)
76
+ return nil unless (field = get_field(id))
77
+
76
78
  field.original_doc["value"]
77
79
  end
78
80
 
@@ -87,7 +89,6 @@ module Ecoportal
87
89
  @fields_by_alt_id[wrapped.alt_id] = wrapped
88
90
  end
89
91
  end
90
-
91
92
  end
92
93
  end
93
94
  end
@@ -30,6 +30,7 @@ module Ecoportal
30
30
  def index_fields
31
31
  @fields_by_id = {}
32
32
  @fields_by_alt_id = {}
33
+
33
34
  doc["fields"].each do |field|
34
35
  wrapped = schema_field_class.new(field)
35
36
  @fields_by_id[wrapped.id] = wrapped
@@ -45,7 +46,6 @@ module Ecoportal
45
46
  )
46
47
  end
47
48
  end
48
-
49
49
  end
50
50
  end
51
51
  end
@@ -38,8 +38,6 @@ module Ecoportal
38
38
  return to_enum(:each) unless block
39
39
  get_all.each(&block)
40
40
  end
41
-
42
-
43
41
  end
44
42
  end
45
43
  end
@@ -22,11 +22,10 @@ module Ecoportal
22
22
  Date.parse(line) rescue return nil, false
23
23
  end
24
24
  end.compact
25
- if multiple
26
- return values, true
27
- else
28
- return values.first, true
29
- end
25
+
26
+ out = values
27
+ out = values.first unless multiple
28
+ [out, true]
30
29
  end
31
30
  end
32
31
  end
@@ -6,29 +6,27 @@ module Ecoportal
6
6
  passthrough :id, :alt_id, :type, :name, :shared, :multiple
7
7
 
8
8
  def clear
9
- if multiple
10
- doc["value"] = []
11
- else
12
- doc["value"] = nil
13
- end
9
+ return doc["value"] = [] if multiple
10
+
11
+ doc["value"] = nil
14
12
  end
15
13
 
16
14
  def value
17
15
  case type
18
16
  when "text", "phone_number", "number", "boolean", "select"
19
- doc["value"]
17
+ doc["value"]
20
18
  when "date"
21
- if doc["value"]
22
- maybe_multiple(doc["value"]) do |v|
23
- Date.iso8601(v)
24
- end
25
- end
19
+ if doc["value"]
20
+ maybe_multiple(doc["value"]) do |v|
21
+ Date.iso8601(v)
22
+ end
23
+ end
26
24
  else
27
- raise "Unknown type #{type}"
25
+ raise "Unknown type #{type}"
28
26
  end
29
27
  end
30
28
 
31
- def value=(value)
29
+ def value=(value) # rubocop:disable Metrics/AbcSize
32
30
  case type
33
31
  when "text", "phone_number", "select"
34
32
  doc["value"] = maybe_multiple(value) do |v|
@@ -36,19 +34,21 @@ module Ecoportal
36
34
  end
37
35
  when "number"
38
36
  maybe_multiple(value) do |v|
39
- unless v.nil? || v.is_a?(Numeric)
40
- raise "Invalid number type #{v.class}"
41
- end
37
+ next if v.nil? || v.is_a?(Numeric)
38
+
39
+ raise "Invalid number type #{v.class}"
42
40
  end
41
+
43
42
  doc["value"] = value
44
43
  when "boolean"
45
44
  doc["value"] = !!value
46
45
  when "date"
47
46
  maybe_multiple(value) do |v|
48
- unless v.nil? || v.respond_to?(:to_date)
49
- raise "Invalid date type #{v.class}"
50
- end
47
+ next if v.nil? || v.respond_to?(:to_date)
48
+
49
+ raise "Invalid date type #{v.class}"
51
50
  end
51
+
52
52
  doc["value"] = maybe_multiple(value) do |v|
53
53
  v&.to_date&.to_s
54
54
  end
@@ -57,12 +57,11 @@ module Ecoportal
57
57
  end
58
58
  end
59
59
 
60
- def maybe_multiple(value)
60
+ def maybe_multiple(value, &block)
61
61
  if multiple
62
- unless value.is_a?(Array)
63
- raise "Expected Array, got #{value.class}"
64
- end
65
- value.map {|v| yield v }
62
+ raise "Expected Array, got #{value.class}" unless value.is_a?(Array)
63
+
64
+ value.map(&block)
66
65
  else
67
66
  yield value
68
67
  end
@@ -6,9 +6,10 @@ module Ecoportal
6
6
  extend Common::BaseClass
7
7
  include Common::Logging
8
8
 
9
- VERSION = "v1"
10
- class_resolver :people_class, "Ecoportal::API::V1::People"
11
- class_resolver :person_schemas_class, "Ecoportal::API::V1::PersonSchemas"
9
+ VERSION = "v1".freeze
10
+
11
+ class_resolver :people_class, "Ecoportal::API::V1::People"
12
+ class_resolver :person_schemas_class, "Ecoportal::API::V1::PersonSchemas"
12
13
 
13
14
  attr_reader :client, :logger
14
15
 
@@ -1,5 +1,5 @@
1
1
  module Ecoportal
2
2
  module API
3
- VERSION = "0.9.8".freeze
3
+ VERSION = "0.10.1".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,35 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecoportal-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tapio Saarinen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-14 00:00:00.000000000 Z
11
+ date: 2024-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 2.4.12
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '3'
23
- type: :development
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 2.4.12
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '3'
33
13
  - !ruby/object:Gem::Dependency
34
14
  name: rspec
35
15
  requirement: !ruby/object:Gem::Requirement
@@ -125,65 +105,59 @@ dependencies:
125
105
  - !ruby/object:Gem::Version
126
106
  version: '0.14'
127
107
  - !ruby/object:Gem::Dependency
128
- name: http
108
+ name: dotenv
129
109
  requirement: !ruby/object:Gem::Requirement
130
110
  requirements:
131
111
  - - "~>"
132
112
  - !ruby/object:Gem::Version
133
- version: '5.1'
134
- - - "<"
135
- - !ruby/object:Gem::Version
136
- version: '6'
113
+ version: '3'
137
114
  type: :runtime
138
115
  prerelease: false
139
116
  version_requirements: !ruby/object:Gem::Requirement
140
117
  requirements:
141
118
  - - "~>"
142
119
  - !ruby/object:Gem::Version
143
- version: '5.1'
144
- - - "<"
145
- - !ruby/object:Gem::Version
146
- version: '6'
120
+ version: '3'
147
121
  - !ruby/object:Gem::Dependency
148
- name: dotenv
122
+ name: elastic-apm
149
123
  requirement: !ruby/object:Gem::Requirement
150
124
  requirements:
151
125
  - - ">="
152
126
  - !ruby/object:Gem::Version
153
- version: '2.8'
127
+ version: '4.7'
154
128
  - - "<"
155
129
  - !ruby/object:Gem::Version
156
- version: '3'
130
+ version: '5'
157
131
  type: :runtime
158
132
  prerelease: false
159
133
  version_requirements: !ruby/object:Gem::Requirement
160
134
  requirements:
161
135
  - - ">="
162
136
  - !ruby/object:Gem::Version
163
- version: '2.8'
137
+ version: '4.7'
164
138
  - - "<"
165
139
  - !ruby/object:Gem::Version
166
- version: '3'
140
+ version: '5'
167
141
  - !ruby/object:Gem::Dependency
168
- name: elastic-apm
142
+ name: http
169
143
  requirement: !ruby/object:Gem::Requirement
170
144
  requirements:
171
- - - ">="
145
+ - - "~>"
172
146
  - !ruby/object:Gem::Version
173
- version: '4.7'
147
+ version: '5.1'
174
148
  - - "<"
175
149
  - !ruby/object:Gem::Version
176
- version: '5'
150
+ version: '6'
177
151
  type: :runtime
178
152
  prerelease: false
179
153
  version_requirements: !ruby/object:Gem::Requirement
180
154
  requirements:
181
- - - ">="
155
+ - - "~>"
182
156
  - !ruby/object:Gem::Version
183
- version: '4.7'
157
+ version: '5.1'
184
158
  - - "<"
185
159
  - !ruby/object:Gem::Version
186
- version: '5'
160
+ version: '6'
187
161
  description:
188
162
  email:
189
163
  - tapio@ecoportal.co.nz
@@ -195,8 +169,10 @@ extensions: []
195
169
  extra_rdoc_files: []
196
170
  files:
197
171
  - ".gitignore"
172
+ - ".markdownlint.json"
198
173
  - ".rspec"
199
174
  - ".rubocop.yml"
175
+ - ".ruby-version"
200
176
  - ".yardopts"
201
177
  - CHANGELOG.md
202
178
  - Gemfile
@@ -250,7 +226,8 @@ files:
250
226
  homepage: https://www.ecoportal.com
251
227
  licenses:
252
228
  - MIT
253
- metadata: {}
229
+ metadata:
230
+ rubygems_mfa_required: 'true'
254
231
  post_install_message:
255
232
  rdoc_options: []
256
233
  require_paths:
@@ -259,14 +236,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
259
236
  requirements:
260
237
  - - ">="
261
238
  - !ruby/object:Gem::Version
262
- version: 2.7.2
239
+ version: 3.2.2
263
240
  required_rubygems_version: !ruby/object:Gem::Requirement
264
241
  requirements:
265
242
  - - ">="
266
243
  - !ruby/object:Gem::Version
267
244
  version: '0'
268
245
  requirements: []
269
- rubygems_version: 3.4.12
246
+ rubygems_version: 3.5.6
270
247
  signing_key:
271
248
  specification_version: 4
272
249
  summary: A collection of helpers for interacting with the ecoPortal MS's various APIs