ecoportal-api-v2 1.1.7 → 2.0.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.
- checksums.yaml +4 -4
- data/.markdownlint.json +4 -0
- data/.rubocop.yml +54 -15
- data/.ruby-version +1 -0
- data/CHANGELOG.md +485 -373
- data/ecoportal-api-v2.gemspec +13 -12
- data/lib/ecoportal/api/common/concerns/benchmarkable.rb +47 -34
- data/lib/ecoportal/api/common/concerns/threadable.rb +41 -0
- data/lib/ecoportal/api/common/concerns.rb +1 -0
- data/lib/ecoportal/api/common/content/array_model.rb +85 -79
- data/lib/ecoportal/api/common/content/class_helpers.rb +34 -31
- data/lib/ecoportal/api/common/content/collection_model.rb +77 -65
- data/lib/ecoportal/api/common/content/double_model.rb +105 -87
- data/lib/ecoportal/api/common/content/wrapped_response.rb +11 -11
- data/lib/ecoportal/api/v2/page/component/reference_field.rb +17 -13
- data/lib/ecoportal/api/v2/page/component.rb +67 -68
- data/lib/ecoportal/api/v2/page/components.rb +9 -9
- data/lib/ecoportal/api/v2/page/force.rb +6 -7
- data/lib/ecoportal/api/v2/page/stages.rb +5 -6
- data/lib/ecoportal/api/v2/page.rb +35 -33
- data/lib/ecoportal/api/v2/pages/page_stage.rb +22 -20
- data/lib/ecoportal/api/v2/pages.rb +18 -14
- data/lib/ecoportal/api/v2/people.rb +2 -3
- data/lib/ecoportal/api/v2/registers.rb +28 -13
- data/lib/ecoportal/api/v2/s3/data.rb +27 -0
- data/lib/ecoportal/api/v2/s3/files/batch_upload.rb +110 -0
- data/lib/ecoportal/api/v2/s3/files/poll.rb +82 -0
- data/lib/ecoportal/api/v2/s3/files/poll_status.rb +52 -0
- data/lib/ecoportal/api/v2/s3/files.rb +132 -0
- data/lib/ecoportal/api/v2/s3/upload.rb +154 -0
- data/lib/ecoportal/api/v2/s3.rb +66 -0
- data/lib/ecoportal/api/v2.rb +10 -3
- data/lib/ecoportal/api/v2_version.rb +1 -1
- metadata +53 -54
data/ecoportal-api-v2.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require "ecoportal/api/v2_version"
|
5
4
|
|
@@ -9,25 +8,27 @@ Gem::Specification.new do |spec|
|
|
9
8
|
spec.authors = ["Oscar Segura"]
|
10
9
|
spec.email = ["rien@ecoportal.co.nz", "oscar@ecoportal.co.nz", "bozydar@ecoportal.co.nz"]
|
11
10
|
|
12
|
-
spec.summary =
|
11
|
+
spec.summary = "A collection of helpers for interacting with the ecoPortal MS's V2 API"
|
13
12
|
spec.homepage = "https://www.ecoportal.com"
|
14
13
|
spec.licenses = %w[MIT]
|
15
14
|
|
16
|
-
spec.
|
15
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
16
|
+
|
17
|
+
spec.required_ruby_version = '>= 3.2.2'
|
17
18
|
|
18
|
-
spec.files
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
20
|
f.match(%r{^(test|spec|features)/})
|
20
21
|
end
|
21
22
|
spec.bindir = "exe"
|
22
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
24
|
spec.require_paths = ["lib"]
|
24
25
|
|
25
|
-
spec.add_development_dependency "
|
26
|
-
spec.add_development_dependency "
|
27
|
-
spec.add_development_dependency "
|
28
|
-
spec.add_development_dependency "
|
29
|
-
spec.add_development_dependency "
|
30
|
-
spec.add_development_dependency "pry" , ">= 0.14"
|
26
|
+
spec.add_development_dependency "pry" , '>= 0.14'
|
27
|
+
spec.add_development_dependency "rake", '>= 13.0.3', "< 14"
|
28
|
+
spec.add_development_dependency "redcarpet", '>= 3.6.0', "< 4"
|
29
|
+
spec.add_development_dependency "rspec", '>= 3.12.0', "< 4"
|
30
|
+
spec.add_development_dependency "yard", '~> 0.9.34'
|
31
31
|
|
32
|
-
spec.add_dependency 'ecoportal-api', '
|
32
|
+
spec.add_dependency 'ecoportal-api', '~> 0.10'
|
33
|
+
spec.add_dependency 'mime-types', '~> 3.5', '>= 3.5.2'
|
33
34
|
end
|
@@ -14,59 +14,63 @@ module Ecoportal
|
|
14
14
|
@benchmark_enabled
|
15
15
|
end
|
16
16
|
|
17
|
-
def benchmarking(ref = nil, print: false)
|
17
|
+
def benchmarking(ref = nil, units: 1, print: false, &block)
|
18
18
|
return yield unless benchmark_enabled?
|
19
|
-
benchmark_mem(ref, print: false) do
|
20
|
-
benchmark_time(ref, print: false)
|
21
|
-
yield
|
22
|
-
end
|
19
|
+
benchmark_mem(ref, units: units, print: false) do
|
20
|
+
benchmark_time(ref, units: units, print: false, &block)
|
23
21
|
end.tap do
|
24
22
|
puts "\n#{bench_summary_ref(ref)}" if print
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
def benchmark_mem(ref = nil, print: false)
|
26
|
+
def benchmark_mem(ref = nil, units: 1, print: false)
|
29
27
|
return yield unless benchmark_enabled?
|
28
|
+
|
30
29
|
memory_before = memory_usage
|
31
30
|
yield.tap do
|
32
31
|
memory_after = memory_usage
|
33
32
|
mb_footprint = ((memory_after - memory_before) / 1024.0).round(2)
|
34
|
-
bench_add_mem(ref, mb_footprint)
|
33
|
+
bench_add_mem(ref, mb_footprint, units: units)
|
35
34
|
puts bench_str_mem(mb, ref: ref, reffix: true) if print
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
def benchmark_time(ref = nil, print: false)
|
38
|
+
def benchmark_time(ref = nil, units: 1, print: false)
|
40
39
|
return yield unless benchmark_enabled?
|
40
|
+
|
41
41
|
result = nil
|
42
42
|
time = benchmark.realtime do
|
43
43
|
result = yield
|
44
44
|
end.round(2)
|
45
|
+
|
45
46
|
result.tap do
|
46
|
-
bench_add_time(ref, time)
|
47
|
+
bench_add_time(ref, time, units: units)
|
47
48
|
puts bench_str_time(time, ref: ref, reffix: true) if print
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
52
|
def benchmark_summary(ref = nil)
|
52
|
-
return ''
|
53
|
+
return '' unless benchmark_enabled?
|
53
54
|
return bench_summary_ref(ref) unless ref == :all
|
54
55
|
|
55
|
-
bench.keys.each_with_object([]) do |
|
56
|
-
out << bench_summary_ref(
|
56
|
+
bench.keys.each_with_object([]) do |rf, out|
|
57
|
+
out << bench_summary_ref(rf)
|
57
58
|
end.join("\n")
|
58
59
|
end
|
59
60
|
|
60
61
|
def bench_summary_ref(ref = nil)
|
61
62
|
ref_lines = bench_summary_ref_lines(ref)
|
62
|
-
"- #{ref}\n"
|
63
|
+
msg = "- #{ref}\n"
|
64
|
+
msg << " • "
|
65
|
+
msg << ref_lines.join("\n • ")
|
66
|
+
msg
|
63
67
|
end
|
64
68
|
|
65
69
|
def bench_summary_ref_lines(ref = nil)
|
66
70
|
ref_bench = bench_get(ref)
|
67
71
|
[
|
68
|
-
bench_str_time(*ref_bench[:time].values_at(:avg, :cnt), ref: ref),
|
69
|
-
bench_str_mem(*ref_bench[:mem].values_at(:avg, :cnt), ref: ref)
|
72
|
+
bench_str_time(*ref_bench[:time].values_at(:avg, :cnt, :last), ref: ref),
|
73
|
+
bench_str_mem(*ref_bench[:mem].values_at(:avg, :cnt, :last), ref: ref)
|
70
74
|
]
|
71
75
|
end
|
72
76
|
|
@@ -79,12 +83,12 @@ module Ecoportal
|
|
79
83
|
@bench ||= {}
|
80
84
|
end
|
81
85
|
|
82
|
-
def bench_add_mem(ref, mem)
|
83
|
-
bench_data_push(bench_get(ref)[:mem], mem)
|
86
|
+
def bench_add_mem(ref, mem, units: 1)
|
87
|
+
bench_data_push(bench_get(ref)[:mem], mem, units: units)
|
84
88
|
end
|
85
89
|
|
86
|
-
def bench_add_time(ref, time)
|
87
|
-
bench_data_push(bench_get(ref)[:time], time)
|
90
|
+
def bench_add_time(ref, time, units: 1)
|
91
|
+
bench_data_push(bench_get(ref)[:time], time, units: units)
|
88
92
|
end
|
89
93
|
|
90
94
|
def bench_get(ref)
|
@@ -96,50 +100,58 @@ module Ecoportal
|
|
96
100
|
|
97
101
|
def bench_data
|
98
102
|
{
|
99
|
-
avg:
|
100
|
-
cnt:
|
103
|
+
avg: nil,
|
104
|
+
cnt: 0,
|
105
|
+
last: nil
|
101
106
|
}
|
102
107
|
end
|
103
108
|
|
104
|
-
def bench_data_push(data, value)
|
105
|
-
total = value + (
|
106
|
-
data[:
|
109
|
+
def bench_data_push(data, value, units: 1)
|
110
|
+
total = value + ((data[:avg] || 0) * data[:cnt])
|
111
|
+
data[:last] = value.round(3)
|
112
|
+
data[:cnt] += units
|
107
113
|
data[:avg] = (total / data[:cnt]).round(3)
|
108
114
|
data
|
109
115
|
end
|
110
116
|
|
111
|
-
def bench_str_mem(mem, count = nil, ref: nil, reffix: false)
|
112
|
-
ref =
|
117
|
+
def bench_str_mem(mem, count = nil, last = nil, ref: nil, reffix: false)
|
118
|
+
ref = nil unless reffix
|
113
119
|
msg = [ref, 'Memory'].compact.join(' -- ')
|
114
|
-
cnt = count ? " (cnt: #{count})" : ''
|
120
|
+
cnt = count ? " (cnt: #{count}; lst: #{last} MB)" : ''
|
115
121
|
"#{msg}: #{mem} MB#{cnt}"
|
116
122
|
end
|
117
123
|
|
118
124
|
def active_support_duration?
|
119
125
|
return false unless Kernel.const_defined?(:ActiveSupport)
|
126
|
+
|
120
127
|
ActiveSupport.const_defined?(:Duration, false)
|
121
128
|
end
|
122
129
|
|
123
|
-
def bench_str_time(time, count = nil, ref: nil, reffix: false)
|
124
|
-
ref =
|
130
|
+
def bench_str_time(time, count = nil, last = nil, ref: nil, reffix: false)
|
131
|
+
ref = nil unless reffix
|
125
132
|
msg = [ref, 'Time'].compact.join(' -- ')
|
126
133
|
total = (time * count).round(2)
|
127
134
|
str_desc = ''
|
135
|
+
|
128
136
|
if active_support_duration? && total >= 60
|
129
137
|
duration = ActiveSupport::Duration.build(total.round)
|
130
|
-
str_desc = "
|
138
|
+
str_desc = " > #{duration_to_s(duration)}"
|
131
139
|
end
|
132
|
-
|
140
|
+
|
141
|
+
cnt = count ? " (cnt: #{count}; lst: #{last} s ; sum: #{total} s#{str_desc})" : ''
|
133
142
|
"#{msg}: #{time} s#{cnt}"
|
134
143
|
end
|
135
144
|
|
136
145
|
def duration_to_s(value)
|
137
|
-
return
|
138
|
-
return
|
146
|
+
return '' unless active_support_duration?
|
147
|
+
return '' if value.nil?
|
148
|
+
|
149
|
+
msg = "Expecint ActiveSupport::Duration. Given: #{value.class}"
|
150
|
+
raise ArgumentError, msg unless value.is_a?(ActiveSupport::Duration)
|
139
151
|
|
140
|
-
raise ArgumentError, "Expecint ActiveSupport::Duration. Given: #{value.class}" unless value.is_a?(ActiveSupport::Duration)
|
141
152
|
parts = value.parts.map {|pair| pair.reverse.join(" ")}
|
142
153
|
return parts.first if parts.length == 1
|
154
|
+
|
143
155
|
[parts[..-2].join(", "), parts.last].join(" and ")
|
144
156
|
end
|
145
157
|
|
@@ -148,6 +160,7 @@ module Ecoportal
|
|
148
160
|
if Gem.win_platform?
|
149
161
|
wmem = `wmic process where processid=#{Process.pid} get WorkingSetSize | findstr "[0-9]"`
|
150
162
|
return 0 unless wmem
|
163
|
+
|
151
164
|
wmem.lines.first.chop.strip.to_i / 1024.0
|
152
165
|
else
|
153
166
|
`ps -o rss= -p #{Process.pid}`.to_i
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Ecoportal
|
2
|
+
module API
|
3
|
+
module Common
|
4
|
+
module Concerns
|
5
|
+
module Threadable
|
6
|
+
private
|
7
|
+
|
8
|
+
def new_thread(threads, max: 20, &block)
|
9
|
+
if max == 1
|
10
|
+
yield
|
11
|
+
return []
|
12
|
+
end
|
13
|
+
|
14
|
+
threads.shift.join if threads.count >= max
|
15
|
+
threads << Thread.new(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def mutex(key = :general)
|
19
|
+
require 'thread'
|
20
|
+
key = key.to_sym
|
21
|
+
@mutex ||= {}
|
22
|
+
@mutex[key] ||= Mutex.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def with_preserved_thread_globals(abort: false, report: true)
|
26
|
+
mutex(:thread_globals).synchronize do
|
27
|
+
aux_thr_aoe = Thread.abort_on_exception
|
28
|
+
aux_thr_roe = Thread.report_on_exception
|
29
|
+
Thread.abort_on_exception = abort
|
30
|
+
Thread.report_on_exception = report
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
Thread.abort_on_exception = aux_thr_aoe
|
34
|
+
Thread.report_on_exception = aux_thr_roe
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -7,13 +7,9 @@ module Ecoportal
|
|
7
7
|
# - Its purpose is to handle an Array of basic objects (i.e. `Date`, `String`, `Number`)
|
8
8
|
class ArrayModel < Content::DoubleModel
|
9
9
|
class TypeMismatchedComparison < StandardError
|
10
|
-
def initialize
|
11
|
-
if this
|
12
|
-
|
13
|
-
end
|
14
|
-
if that
|
15
|
-
msg += " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'."
|
16
|
-
end
|
10
|
+
def initialize(this: nil, that: msg = "Trying to compare objects with different behavior.")
|
11
|
+
msg << " From object with 'order_matters: #{this.order_matters?}' and 'uniq: #{this.uniq?}'." if this
|
12
|
+
msg << " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'." if that
|
17
13
|
super(msg)
|
18
14
|
end
|
19
15
|
end
|
@@ -26,8 +22,9 @@ module Ecoportal
|
|
26
22
|
# @param a [ArrayModel]
|
27
23
|
# @param b [ArrayModel]
|
28
24
|
# @return [Boolean] `true` if both elements have same behaviour
|
29
|
-
def same_type?(a, b)
|
30
|
-
|
25
|
+
def same_type?(a, b) # rubocop:disable Naming/MethodParameterName
|
26
|
+
msg = "To use this comparison both objects should be `ArrayModel`"
|
27
|
+
raise msg unless a.is_a?(ArrayModel) && b.is_a?(ArrayModel)
|
31
28
|
(a.order_matters? == b.order_matters?) && (a.uniq? == b.uniq?)
|
32
29
|
end
|
33
30
|
end
|
@@ -38,15 +35,29 @@ module Ecoportal
|
|
38
35
|
super(doc, parent: parent, key: key, read_only: read_only)
|
39
36
|
end
|
40
37
|
|
41
|
-
def order_matters
|
42
|
-
|
38
|
+
def order_matters?
|
39
|
+
self.class.order_matters
|
40
|
+
end
|
41
|
+
|
42
|
+
def uniq?
|
43
|
+
self.class.uniq
|
44
|
+
end
|
43
45
|
|
44
|
-
def length
|
45
|
-
|
46
|
-
|
46
|
+
def length
|
47
|
+
count
|
48
|
+
end
|
49
|
+
|
50
|
+
def empty?
|
51
|
+
count&.zero?
|
52
|
+
end
|
53
|
+
|
54
|
+
def present?
|
55
|
+
count&.positive?
|
56
|
+
end
|
47
57
|
|
48
58
|
def each(&block)
|
49
59
|
return to_enum(:each) unless block
|
60
|
+
|
50
61
|
_items.each(&block)
|
51
62
|
end
|
52
63
|
|
@@ -66,10 +77,10 @@ module Ecoportal
|
|
66
77
|
_items.slice(0..-1)
|
67
78
|
end
|
68
79
|
|
69
|
-
# @param
|
80
|
+
# @param other [Object, Array<Object>, ArrayModel] the value(s) of the new object
|
70
81
|
# @return [ArrayModel] a new object with the current class
|
71
|
-
def new_from(
|
72
|
-
self.class.new(into_a(
|
82
|
+
def new_from(other)
|
83
|
+
self.class.new(into_a(other))
|
73
84
|
end
|
74
85
|
|
75
86
|
# @return [ArrayModel] a copy of the current object
|
@@ -93,28 +104,28 @@ module Ecoportal
|
|
93
104
|
# @param pos [Integer] the position of the element
|
94
105
|
# @param value [String, Date, Number] the element
|
95
106
|
# @return [Date, String, Number]
|
96
|
-
def []=(
|
107
|
+
def []=(pos, value)
|
97
108
|
_items[pos] = value
|
98
109
|
on_change
|
99
110
|
self[pos]
|
100
111
|
end
|
101
112
|
|
102
113
|
# Compares with an `Array` or another `ArrayModel`
|
103
|
-
# @param
|
104
|
-
def ==(
|
105
|
-
return true
|
106
|
-
return false unless (
|
107
|
-
|
114
|
+
# @param other [ArrayModel, Array]
|
115
|
+
def ==(other)
|
116
|
+
return true if equal?(other)
|
117
|
+
return false unless (other.class == self.class) || other.is_a?(Array)
|
118
|
+
|
119
|
+
case other
|
108
120
|
when Array
|
109
|
-
self == new_from(
|
121
|
+
self == new_from(other)
|
110
122
|
when ArrayModel
|
111
|
-
|
112
|
-
raise TypeMismatchedComparison.new(this: self, that: a) unless self.class.same_type?(self, a)
|
123
|
+
raise TypeMismatchedComparison.new(this: self, that: other) unless self.class.same_type?(self, other)
|
113
124
|
|
114
|
-
if
|
115
|
-
_items ==
|
125
|
+
if order_matters?
|
126
|
+
_items == other.to_a
|
116
127
|
else
|
117
|
-
(_items -
|
128
|
+
(_items - other.to_a).empty? && (other.to_a - _items).empty?
|
118
129
|
end
|
119
130
|
end
|
120
131
|
end
|
@@ -154,11 +165,10 @@ module Ecoportal
|
|
154
165
|
end
|
155
166
|
|
156
167
|
# Resets the `Array` by keeping its reference and adds the value(s)
|
157
|
-
# @param
|
158
|
-
|
159
|
-
def <(values)
|
168
|
+
# @param other [Object, Array<Object>, ArrayModel] the value(s) to be added
|
169
|
+
def <(other)
|
160
170
|
_items.clear
|
161
|
-
self <<
|
171
|
+
self << other
|
162
172
|
end
|
163
173
|
|
164
174
|
# Clears the `Array` keeping its reference
|
@@ -169,25 +179,25 @@ module Ecoportal
|
|
169
179
|
end
|
170
180
|
|
171
181
|
# Concat to new
|
172
|
-
def +(
|
173
|
-
new_from(
|
182
|
+
def +(other)
|
183
|
+
new_from(to_a + into_a(other))
|
174
184
|
end
|
175
185
|
|
176
186
|
# Join
|
177
|
-
# @param
|
187
|
+
# @param other [Object, Array<Object>, ArrayModel] the value(s) to be joined
|
178
188
|
# @return [ArrayModel] a new object instance with the intersection done
|
179
|
-
def |(
|
180
|
-
|
181
|
-
new_from(to_a +
|
189
|
+
def |(other)
|
190
|
+
oth = new_from(other) - self
|
191
|
+
new_from(to_a + oth.to_a)
|
182
192
|
end
|
183
193
|
|
184
194
|
# Intersect
|
185
|
-
# @param
|
195
|
+
# @param other [Object, Array<Object>, ArrayModel] the value(s) to be deleted
|
186
196
|
# @return [ArrayModel] a new object instance with the intersection done
|
187
|
-
def &(
|
188
|
-
|
189
|
-
|
190
|
-
delta.delete!(*into_a(
|
197
|
+
def &(other)
|
198
|
+
dup.tap do |out|
|
199
|
+
dup.tap do |delta|
|
200
|
+
delta.delete!(*into_a(other))
|
191
201
|
out.delete!(*into_a(delta))
|
192
202
|
end
|
193
203
|
end
|
@@ -196,9 +206,9 @@ module Ecoportal
|
|
196
206
|
# Subtract
|
197
207
|
# @param value [Object, Array<Object>, ArrayModel] the value(s) to be deleted
|
198
208
|
# @return [ArrayModel] a **copy** of the object with the elements subtracted
|
199
|
-
def -(
|
200
|
-
|
201
|
-
copy.delete!(*into_a(
|
209
|
+
def -(other)
|
210
|
+
dup.tap do |copy|
|
211
|
+
copy.delete!(*into_a(other))
|
202
212
|
end
|
203
213
|
end
|
204
214
|
|
@@ -206,7 +216,7 @@ module Ecoportal
|
|
206
216
|
def delete!(*values)
|
207
217
|
values.map do |v|
|
208
218
|
deletion!(v)
|
209
|
-
end.tap do |
|
219
|
+
end.tap do |_r|
|
210
220
|
on_change
|
211
221
|
end
|
212
222
|
end
|
@@ -216,43 +226,41 @@ module Ecoportal
|
|
216
226
|
# @param val1 [Object] the first value to swap
|
217
227
|
# @param val2 [Object] the second value to swap
|
218
228
|
# @return [Integer] the new of `value1`, `nil` if it wasn't moved
|
219
|
-
def swap(
|
220
|
-
index(
|
221
|
-
if dest && pos = index(
|
222
|
-
_items[dest] =
|
223
|
-
_items[pos] =
|
229
|
+
def swap(val_1, val_2)
|
230
|
+
index(val_2).tap do |dest|
|
231
|
+
if dest && (pos = index(val_1))
|
232
|
+
_items[dest] = val_1
|
233
|
+
_items[pos] = val_2
|
224
234
|
end
|
225
235
|
end
|
226
236
|
end
|
227
237
|
|
228
238
|
def insert_one(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
229
|
-
|
230
|
-
return
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
+
idx = index(value)
|
240
|
+
return idx if idx && uniq?
|
241
|
+
|
242
|
+
pos =
|
243
|
+
if used_param?(pos) && pos
|
244
|
+
pos
|
245
|
+
elsif used_param?(before) && before
|
246
|
+
index(before)
|
247
|
+
elsif used_param?(after) && after
|
248
|
+
if (idx = index(after)) then idx + 1 end
|
249
|
+
end
|
239
250
|
|
251
|
+
# use last position as default
|
240
252
|
pos ||= length
|
241
|
-
pos.tap do |
|
253
|
+
pos.tap do |_i|
|
242
254
|
_items.insert(pos, value)
|
243
255
|
on_change
|
244
256
|
end
|
245
257
|
end
|
246
258
|
|
247
259
|
# TODO
|
248
|
-
def move(value, pos: NOT_USED,
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
on_change
|
253
|
-
end
|
254
|
-
pos
|
255
|
-
end
|
260
|
+
def move(value, pos: NOT_USED, _before: NOT_USED, _after: NOT_USED)
|
261
|
+
return unless (idx = index(value))
|
262
|
+
on_change unless idx == pos
|
263
|
+
pos
|
256
264
|
end
|
257
265
|
|
258
266
|
protected
|
@@ -266,17 +274,15 @@ module Ecoportal
|
|
266
274
|
def into_a(value)
|
267
275
|
raise "Can't convert to 'Array' a 'Hash', as is a key_value pair Enumerable" if value.is_a?(Hash)
|
268
276
|
return value.to_a.slice(0..-1) if value.is_a?(Enumerable)
|
277
|
+
|
269
278
|
[].push(value).compact
|
270
279
|
end
|
271
280
|
|
272
281
|
def deletion!(value)
|
273
|
-
if
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
else
|
278
|
-
_items.delete(value)
|
279
|
-
end
|
282
|
+
return _items.delete(value) if uniq?
|
283
|
+
return unless (idx = _items.index(value))
|
284
|
+
|
285
|
+
_items.slice!(idx)
|
280
286
|
end
|
281
287
|
end
|
282
288
|
end
|