ecoportal-api-v2 0.8.6 → 0.8.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +73 -28
- data/bin/console +1 -1
- data/ecoportal-api-v2.gemspec +5 -5
- data/lib/ecoportal/api-v2.rb +2 -2
- data/lib/ecoportal/api/common.v2.rb +8 -0
- data/lib/ecoportal/api/common/content.rb +1 -0
- data/lib/ecoportal/api/common/content/array_model.rb +8 -6
- data/lib/ecoportal/api/common/content/collection_model.rb +45 -20
- data/lib/ecoportal/api/common/content/double_model.rb +98 -9
- data/lib/ecoportal/api/common/content/hash_diff_patch.rb +44 -22
- data/lib/ecoportal/api/common/content/model_helpers.rb +36 -0
- data/lib/ecoportal/api/v2/page.rb +15 -2
- data/lib/ecoportal/api/v2/page/component.rb +44 -10
- data/lib/ecoportal/api/v2/page/component/action.rb +17 -8
- data/lib/ecoportal/api/v2/page/component/action_field.rb +37 -2
- data/lib/ecoportal/api/v2/page/component/chart_field.rb +43 -5
- data/lib/ecoportal/api/v2/page/component/chart_field/benchmark.rb +30 -0
- data/lib/ecoportal/api/v2/page/component/chart_field/config.rb +23 -0
- data/lib/ecoportal/api/v2/page/component/chart_field/frequency.rb +3 -4
- data/lib/ecoportal/api/v2/page/component/chart_field/heatmap.rb +1 -3
- data/lib/ecoportal/api/v2/page/component/chart_field/indicator.rb +4 -5
- data/lib/ecoportal/api/v2/page/component/chart_field/multiseries.rb +3 -5
- data/lib/ecoportal/api/v2/page/component/chart_field/sankey.rb +1 -3
- data/lib/ecoportal/api/v2/page/component/chart_field/serie.rb +3 -4
- data/lib/ecoportal/api/v2/page/component/chart_field/series_config.rb +5 -7
- data/lib/ecoportal/api/v2/page/component/chart_fr_field.rb +7 -5
- data/lib/ecoportal/api/v2/page/component/checklist_field.rb +1 -1
- data/lib/ecoportal/api/v2/page/component/checklist_item.rb +7 -5
- data/lib/ecoportal/api/v2/page/component/date_field.rb +71 -4
- data/lib/ecoportal/api/v2/page/component/file.rb +14 -3
- data/lib/ecoportal/api/v2/page/component/files_field.rb +37 -1
- data/lib/ecoportal/api/v2/page/component/gauge_field.rb +2 -2
- data/lib/ecoportal/api/v2/page/component/gauge_stop.rb +5 -5
- data/lib/ecoportal/api/v2/page/component/geo_coordinates.rb +13 -0
- data/lib/ecoportal/api/v2/page/component/geo_field.rb +4 -1
- data/lib/ecoportal/api/v2/page/component/image.rb +2 -1
- data/lib/ecoportal/api/v2/page/component/images_field.rb +57 -1
- data/lib/ecoportal/api/v2/page/component/number_field.rb +1 -0
- data/lib/ecoportal/api/v2/page/component/people_field.rb +117 -7
- data/lib/ecoportal/api/v2/page/component/people_viewable_field.rb +14 -0
- data/lib/ecoportal/api/v2/page/component/plain_text_field.rb +34 -2
- data/lib/ecoportal/api/v2/page/component/reference_field.rb +32 -3
- data/lib/ecoportal/api/v2/page/component/selection_field.rb +65 -7
- data/lib/ecoportal/api/v2/page/component/selection_option.rb +16 -5
- data/lib/ecoportal/api/v2/page/component/signature_field.rb +3 -2
- data/lib/ecoportal/api/v2/page/component/tag_field.rb +31 -1
- data/lib/ecoportal/api/v2/page/components.rb +8 -3
- data/lib/ecoportal/api/v2/page/permission_flags.rb +67 -0
- data/lib/ecoportal/api/v2/page/permit.rb +15 -0
- data/lib/ecoportal/api/v2/page/section.rb +70 -9
- data/lib/ecoportal/api/v2/page/sections.rb +64 -6
- data/lib/ecoportal/api/v2/page/stage.rb +12 -4
- data/lib/ecoportal/api/v2/page/stages.rb +7 -7
- data/lib/ecoportal/api/v2/pages/page_stage.rb +3 -3
- data/lib/ecoportal/api/v2_version.rb +5 -0
- metadata +17 -10
- data/lib/ecoportal/api/common.rb +0 -18
- data/lib/ecoportal/api/v2/version.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8961e37170e3ffe06d26c17daa6672a15d595ff91c5e8fb38253549b166057a
|
4
|
+
data.tar.gz: c9b25eb42cfa9cb45cee3d830067eddc7d4191fa87f0fd4e35620e346ca27922
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a68c58f62600b78745caff84d7e0dbda83e2f79cba8d41ca08ffbcf361060bd614fc6957f38878bb09d41dc6db1fcff3e307dd0072d21d960073683e6881fdbc
|
7
|
+
data.tar.gz: 998e1409fd0674bc409ab2ff1dcfb68f42a0dd37bca8eab040750cc8cc10ca2651fb98dc61adf3d44b0b0dbdc0bccfe384786cdd79ad1fd9ed96d12a00f3a4b4
|
data/CHANGELOG.md
CHANGED
@@ -1,34 +1,99 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [0.8.
|
4
|
+
## [0.8.10] - 2021-08-xx
|
5
5
|
|
6
6
|
### Added
|
7
|
-
- `Ecoportal::API::
|
7
|
+
- `Ecoportal::API::Common::Content::CollectionModel#[]` now supports position as well
|
8
|
+
- `Ecoportal::API::V2::Page::Component::FilesField#add_file`: support for adding files
|
9
|
+
- `Ecoportal::API::V2::Page::Component::PeopleField#viewable_fields`: support for managing `viewable_fields`
|
8
10
|
|
9
11
|
### Changed
|
12
|
+
|
10
13
|
### Fixed
|
14
|
+
- `Ecoportal::API::V2::Page::Component::FilesField`: was not requiring `File`
|
15
|
+
- `Ecoportal::API::V2::Page::Component::NumberField#value`: it was missing :/
|
16
|
+
- `Ecoportal::API::Common::Content::HashDiffPatch` did not support nested objects in Arrays, where the nested object wouldn't have a `patch_ver`. This **fix** allows for it
|
17
|
+
- `Ecoportal::API::Common::Content::DoubleModel.passforced` to define `methods` that should always be present. This allows to define `patch_ver` as a forced `key` in models that have it
|
18
|
+
- The enforcement (`self.class.enforce!`) happens on `initialize`
|
19
|
+
- `passenforced` subjacent model `forced_model_keys` is inheritable
|
20
|
+
- `Ecoportal::API::Common::Content::CollectionModel`:
|
21
|
+
- Method `upsert!` was not working fine the parameters `pos`, `before` and `after`
|
22
|
+
- Method `delete!` did not support position
|
23
|
+
|
24
|
+
## [0.8.9] - 2021-08-16
|
11
25
|
|
26
|
+
### Added
|
27
|
+
- `Ecoportal::API::Common::Content::ModelHelpers`
|
28
|
+
- Starting with `#same_string?`, this lib aims to offer a full set of helper comparers.
|
29
|
+
- `Ecoportal::API::V2::Page::Components#get_by_id`
|
30
|
+
- In future changes, method `[]` might be overriding the method of the parent class `CollectionModel`.
|
31
|
+
- `Ecoportal::API::V2::Page::PermissionFlags` to offer support to `can_permission`, `subscribed`, etc.
|
32
|
+
- `Ecoportal::API::V2::Page::Section#add_component` super handy helper to add fields to sections.
|
33
|
+
- `Ecoportal::API::V2::Page::Component::PeopleField#delete` to remove people using their ids.
|
34
|
+
- `Ecoportal::API::V2::Page::Component::GeoField` **added** suport for `#coordinates`
|
35
|
+
- With embedded object `Ecoportal::API::V2::Page::Component::GeoCoordinates`
|
36
|
+
- `#configure` method, to all the `Component` types (but `ChartField` s)
|
37
|
+
- This method allows to quickly set field properties.
|
38
|
+
- `Ecoportal::API::V2::Page::Sections#between`, aiming to obtain sections between two other ones
|
12
39
|
|
13
|
-
|
40
|
+
|
41
|
+
### Changed
|
42
|
+
- `Ecoportal::API::V2::Page::Section` real support for `split` sections (right vs left)
|
43
|
+
- This is actually a **FIX**
|
44
|
+
- `Ecoportal::API::V2::Page::Component::DateField#create_event`
|
45
|
+
- Now it switches to _allow future dates_
|
46
|
+
- `Ecoportal::API::V2::Page::Component::SelectionField#add_option`, the `name` parameter is now optional
|
47
|
+
- This change aims to make it consistent with the back-end.
|
48
|
+
- To its actual `Boolean` type some properties
|
49
|
+
- All `Component` types
|
50
|
+
|
51
|
+
### Fixed
|
52
|
+
- `Ecoportal::API::Common::Content::HashDiffPatch` did not support `Hash` values without `id` or `patch_ver`
|
53
|
+
- This fix should allow them to flow to the update
|
54
|
+
- `Ecoportal::API::V2::Page::Component::ChartField` did not have `doc` for `mode` based configuration
|
55
|
+
- `Ecoportal::API::Common::Content::ArrayModel#insert_one`
|
56
|
+
- When `pos`, `before` & `after` were `nil` it was failing to attach the element.
|
57
|
+
- `Ecoportal::API::V2::Page::Sections#add` was not adding in the correct order
|
58
|
+
- `Ecoportal::API::V2::Page::Section.new_doc` was unnecessarily giving `9999` as default weight
|
59
|
+
|
60
|
+
## [0.8.8] - 2021-08-03
|
14
61
|
|
15
62
|
### Added
|
63
|
+
- `Ecoportal::API::V2::Page::Component::ChartField::Benchmark`
|
64
|
+
- Support to convert selection options between numeric and text type.
|
65
|
+
- Add `Permit` object to `Page` and `Stage`
|
66
|
+
|
16
67
|
### Changed
|
17
|
-
-
|
68
|
+
- Removed `Stages.ordered_stages`: detected bug with Enumerable iteration
|
69
|
+
|
70
|
+
|
71
|
+
## [0.8.7] - 2021-05-25
|
72
|
+
|
73
|
+
### Changed
|
74
|
+
- Upgrade `ecoportal-api` gem
|
75
|
+
|
18
76
|
### Fixed
|
77
|
+
- Requiring `api/common` from 2 different ends
|
78
|
+
|
79
|
+
## [0.8.6] - 2021-02-23
|
80
|
+
|
81
|
+
### Added
|
82
|
+
- `Ecoportal::API::V2::Page::Component::SelectionField` added methods `#numeric!` `#text!`
|
83
|
+
|
84
|
+
## [0.8.5] - 2021-02-22
|
85
|
+
|
86
|
+
### Changed
|
87
|
+
- upgrade
|
19
88
|
|
20
89
|
|
21
90
|
## [0.8.4] - 2021-02-22
|
22
91
|
|
23
|
-
### Added
|
24
92
|
### Changed
|
25
93
|
- roll back `ecoportal-api` dependency
|
26
94
|
|
27
|
-
### Fixed
|
28
|
-
|
29
95
|
## [0.8.3] - 2021-02-22
|
30
96
|
|
31
|
-
### Added
|
32
97
|
### Changed
|
33
98
|
- updated `rspec` for expected patch data on `delete` operation.
|
34
99
|
|
@@ -37,23 +102,16 @@ All notable changes to this project will be documented in this file.
|
|
37
102
|
|
38
103
|
## [0.8.2] - 2021-02-21
|
39
104
|
|
40
|
-
### Added
|
41
105
|
### Changed
|
42
106
|
- some necessary changes for the new gem to be active
|
43
107
|
|
44
|
-
### Fixed
|
45
|
-
|
46
108
|
## [0.8.1] - 2021-02-21
|
47
109
|
|
48
|
-
### Added
|
49
110
|
### Changed
|
50
111
|
- renamed parameters (backwards incompatible change):
|
51
112
|
- `Ecoportal::API::V2::Pages::Stages` methods `#get` and `#update`
|
52
113
|
- updated `Ecoportal::API::V2::Pages#` accordingly
|
53
114
|
|
54
|
-
### Fixed
|
55
|
-
|
56
|
-
|
57
115
|
## MOVED TO GEM `ecoportal-api-v2` ##
|
58
116
|
|
59
117
|
## [0.7.5] - 2021-02-21
|
@@ -147,42 +205,29 @@ All notable changes to this project will be documented in this file.
|
|
147
205
|
- automatic key builder
|
148
206
|
- helper: `Ecoportal::API::V2::v2key` method
|
149
207
|
- `user_key:` and `org_key:` as constructor methods for `Ecoportal::API::V2`
|
150
|
-
### Changed
|
151
|
-
### Fixed
|
152
208
|
|
153
209
|
## [0.7.1] - 2020-10-07
|
154
210
|
|
155
|
-
### Added
|
156
211
|
### Changed
|
157
212
|
- updated dependencies
|
158
|
-
### Fixed
|
159
|
-
|
160
213
|
|
161
214
|
## [0.7.0] - 2020-09-10
|
162
215
|
|
163
|
-
### Added
|
164
216
|
### Changed
|
165
217
|
- updated dependencies
|
166
|
-
### Fixed
|
167
218
|
|
168
219
|
## [0.6.1] - 2020-07-11
|
169
220
|
|
170
221
|
### Added
|
171
222
|
- `Ecoportal::API::Common::Content::DoubleModel#pretty_print`
|
172
|
-
### Changed
|
173
|
-
### Fixed
|
174
223
|
|
175
224
|
## [0.6.0] - 2020-07-11
|
176
225
|
|
177
|
-
### Added
|
178
226
|
### Changed
|
179
227
|
- upgraded `ecoportal-api` gem
|
180
|
-
### Fixed
|
181
228
|
|
182
229
|
## [0.5.9] - 2020-07-02
|
183
230
|
|
184
231
|
### Added
|
185
232
|
- helper `Ecoportal::API::Common::Content::StringDigest#indexable_label`: to see the part of a label that gets indexed
|
186
233
|
- this `CHANGELOG.md` file
|
187
|
-
### Changed
|
188
|
-
### Fixed
|
data/bin/console
CHANGED
data/ecoportal-api-v2.gemspec
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
2
|
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "ecoportal/api/
|
4
|
+
require "ecoportal/api/v2_version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "ecoportal-api-v2"
|
8
|
-
spec.version = Ecoportal::API::
|
8
|
+
spec.version = Ecoportal::API::GEM2_VERSION
|
9
9
|
spec.authors = ["Oscar Segura"]
|
10
10
|
spec.email = ["rien@ecoportal.co.nz", "oscar@ecoportal.co.nz", "bozydar@ecoportal.co.nz"]
|
11
11
|
|
@@ -22,12 +22,12 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_development_dependency "bundler", ">= 2.2.
|
25
|
+
spec.add_development_dependency "bundler", ">= 2.2.17", "< 2.3"
|
26
26
|
spec.add_development_dependency "rspec", ">= 3.10.0", "< 3.11"
|
27
27
|
spec.add_development_dependency "rake", ">= 13.0.3", "< 13.1"
|
28
28
|
spec.add_development_dependency "yard", ">= 0.9.26", "< 0.10"
|
29
29
|
spec.add_development_dependency "redcarpet", ">= 3.5.1", "< 3.6"
|
30
|
-
spec.add_development_dependency "pry" , "
|
30
|
+
spec.add_development_dependency "pry" , ">= 0.14"
|
31
31
|
|
32
|
-
spec.add_dependency 'ecoportal-api', '>= 0.8.
|
32
|
+
spec.add_dependency 'ecoportal-api', '>= 0.8.3', '< 0.9'
|
33
33
|
end
|
data/lib/ecoportal/api-v2.rb
CHANGED
@@ -9,6 +9,7 @@ end
|
|
9
9
|
|
10
10
|
require 'ecoportal/api/common/content/class_helpers'
|
11
11
|
require 'ecoportal/api/common/content/string_digest'
|
12
|
+
require 'ecoportal/api/common/content/model_helpers'
|
12
13
|
require 'ecoportal/api/common/content/double_model'
|
13
14
|
require 'ecoportal/api/common/content/array_model'
|
14
15
|
require 'ecoportal/api/common/content/collection_model'
|
@@ -3,7 +3,8 @@ module Ecoportal
|
|
3
3
|
module Common
|
4
4
|
module Content
|
5
5
|
# Class to handle a plain Array embedded in a Hashed model.
|
6
|
-
# @note
|
6
|
+
# @note
|
7
|
+
# - Its purpose is to handle an Array of basic objects (i.e. `Date`, `String`, `Number`)
|
7
8
|
class ArrayModel < Content::DoubleModel
|
8
9
|
class TypeMismatchedComparison < Exception
|
9
10
|
def initialize (this: nil, that: msg = "Trying to compare objects with different behavior.")
|
@@ -222,15 +223,16 @@ module Ecoportal
|
|
222
223
|
def insert_one(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
223
224
|
i = index(value)
|
224
225
|
return i if (i && uniq?)
|
225
|
-
|
226
226
|
pos = case
|
227
227
|
when used_param?(pos)
|
228
|
-
pos
|
228
|
+
pos || length
|
229
229
|
when used_param?(before)
|
230
|
-
index(before)
|
230
|
+
before ? index(before) : length
|
231
231
|
when used_param?(after)
|
232
|
-
if
|
233
|
-
i + 1
|
232
|
+
if after
|
233
|
+
if i = index(after) then i + 1 end
|
234
|
+
else
|
235
|
+
length
|
234
236
|
end
|
235
237
|
else
|
236
238
|
length
|
@@ -2,6 +2,9 @@ module Ecoportal
|
|
2
2
|
module API
|
3
3
|
module Common
|
4
4
|
module Content
|
5
|
+
# CollectionModel aims to deal with Arrays of actual objects.
|
6
|
+
# @note to be able to refer to the correct element of the Collection,
|
7
|
+
# it is required that those elements have a unique `key` that allows to identify them
|
5
8
|
class CollectionModel < Content::DoubleModel
|
6
9
|
|
7
10
|
class << self
|
@@ -140,17 +143,21 @@ module Ecoportal
|
|
140
143
|
end
|
141
144
|
|
142
145
|
# Get an element usign the `key`.
|
146
|
+
# @param value [String, Hash, Ecoportal::API::Common::Content::DoubleModel]
|
147
|
+
# @return [Object] the `items_class` element object
|
143
148
|
def [](value)
|
144
149
|
items_by_key[get_key(value)]
|
145
150
|
end
|
146
151
|
|
152
|
+
# @return [Array<Object>] the `items_class` element object
|
147
153
|
def values_at(*keys)
|
148
154
|
keys.map {|key| self[key]}
|
149
155
|
end
|
150
156
|
|
151
157
|
# Tries to find the element `value`, if it exists, it updates it
|
152
|
-
#
|
153
|
-
# @
|
158
|
+
# Otherwise it pushes it to the end
|
159
|
+
# @value [Hash, Ecoportal::API::Common::Content::DoubleModel] the eleement to be added
|
160
|
+
# @return [Object] the `items_class` element object
|
154
161
|
def upsert!(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
155
162
|
unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
|
156
163
|
raise "'Content::DoubleModel' or 'Hash' doc required"
|
@@ -160,15 +167,20 @@ module Ecoportal
|
|
160
167
|
if item = self[value]
|
161
168
|
item.replace_doc(item_doc)
|
162
169
|
else
|
163
|
-
_doc_upsert(item_doc, pos: pos, before: before, after: after)
|
170
|
+
pos_idx = _doc_upsert(item_doc, pos: pos, before: before, after: after)
|
164
171
|
end
|
165
172
|
(item || self[item_doc]).tap do |item|
|
166
173
|
yield(item) if block_given?
|
167
174
|
end
|
168
175
|
end
|
169
176
|
|
177
|
+
# Deletes `value` from this `CollectionModel` instance
|
178
|
+
# @param value [String, Hash, Ecoportal::API::Common::Content::DoubleModel]
|
179
|
+
# - When used as `String`, the `key` value (i.e. `id` value) is expected
|
180
|
+
# - When used as `Hash`, it should be the `doc` of the target element
|
181
|
+
# - When used as `DoubleModel`, it should be the specific object to be deleted
|
170
182
|
def delete!(value)
|
171
|
-
unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
|
183
|
+
unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel) || value.is_a?(String)
|
172
184
|
raise "'Content::DoubleModel' or 'Hash' doc required"
|
173
185
|
end
|
174
186
|
if item = self[value]
|
@@ -186,7 +198,7 @@ module Ecoportal
|
|
186
198
|
variables_remove!
|
187
199
|
end
|
188
200
|
|
189
|
-
# Gets the `key` of the object
|
201
|
+
# Gets the `key` of the object `value`
|
190
202
|
def get_key(value)
|
191
203
|
case value
|
192
204
|
when Content::DoubleModel
|
@@ -195,6 +207,8 @@ module Ecoportal
|
|
195
207
|
value[items_key]
|
196
208
|
when String
|
197
209
|
value
|
210
|
+
when Numeric
|
211
|
+
get_key(self.to_a[value])
|
198
212
|
end
|
199
213
|
end
|
200
214
|
|
@@ -235,27 +249,22 @@ module Ecoportal
|
|
235
249
|
super
|
236
250
|
end
|
237
251
|
|
252
|
+
# Deletes `value` from `doc` (here referred as `_doc_items`)
|
253
|
+
# @return [Object] the element deleted from `doc`
|
238
254
|
def _doc_delete(value)
|
239
255
|
if current_pos = _doc_key(value)
|
240
|
-
_doc_items.delete_at(current_pos)
|
241
|
-
|
256
|
+
_doc_items.delete_at(current_pos).tap do |deleted|
|
257
|
+
on_change
|
258
|
+
end
|
242
259
|
end
|
243
260
|
end
|
244
261
|
|
245
262
|
def _doc_upsert(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
246
|
-
current_pos =
|
247
|
-
|
248
|
-
|
249
|
-
pos
|
250
|
-
when used_param?(before)
|
251
|
-
_doc_key(before)
|
252
|
-
when used_param?(after)
|
253
|
-
#puts "to add after #{after.id}"
|
254
|
-
if i = _doc_key(after)
|
255
|
-
i + 1
|
256
|
-
end
|
257
|
-
end
|
263
|
+
current_pos = if elem = self[value]
|
264
|
+
_doc_key(elem)
|
265
|
+
end
|
258
266
|
|
267
|
+
pos = scope_position(pos: pos, before: before, after: after)
|
259
268
|
pos ||= current_pos
|
260
269
|
|
261
270
|
if current_pos && pos
|
@@ -264,7 +273,6 @@ module Ecoportal
|
|
264
273
|
end
|
265
274
|
|
266
275
|
pos = (pos && pos < _doc_items.length)? pos : _doc_items.length
|
267
|
-
|
268
276
|
pos.tap do |i|
|
269
277
|
_doc_items.insert(pos, value)
|
270
278
|
on_change
|
@@ -272,6 +280,23 @@ module Ecoportal
|
|
272
280
|
|
273
281
|
end
|
274
282
|
|
283
|
+
def scope_position(pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
284
|
+
case
|
285
|
+
when used_param?(pos)
|
286
|
+
if elem = self[pos]
|
287
|
+
_doc_key(elem) - 1
|
288
|
+
end
|
289
|
+
when used_param?(before)
|
290
|
+
if elem = self[before]
|
291
|
+
_doc_key(elem) - 1
|
292
|
+
end
|
293
|
+
when used_param?(after)
|
294
|
+
if elem = self[after]
|
295
|
+
_doc_key(elem)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
275
300
|
end
|
276
301
|
end
|
277
302
|
end
|
@@ -10,6 +10,7 @@ module Ecoportal
|
|
10
10
|
class DoubleModel < Common::BaseModel
|
11
11
|
NOT_USED = Common::Content::ClassHelpers::NOT_USED
|
12
12
|
extend Common::Content::ClassHelpers
|
13
|
+
include Common::Content::ModelHelpers
|
13
14
|
|
14
15
|
class UnlinkedModel < Exception
|
15
16
|
def initialize (msg = "Something went wrong when linking the document.", from: nil, key: nil)
|
@@ -36,6 +37,8 @@ module Ecoportal
|
|
36
37
|
|
37
38
|
# Same as `attr_reader` but links to a subjacent `Hash` model property
|
38
39
|
# @note it does **not** create an _instance variable_
|
40
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
41
|
+
# as well as its `key` in the underlying `Hash` model.
|
39
42
|
def pass_reader(*methods)
|
40
43
|
methods.each do |method|
|
41
44
|
method = method.to_s.freeze
|
@@ -51,6 +54,8 @@ module Ecoportal
|
|
51
54
|
|
52
55
|
# Same as `attr_writer` but links to a subjacent `Hash` model property
|
53
56
|
# @note it does **not** create an _instance variable_
|
57
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
58
|
+
# as well as its `key` in the underlying `Hash` model.
|
54
59
|
def pass_writer(*methods)
|
55
60
|
methods.each do |method|
|
56
61
|
method = method.to_s.freeze
|
@@ -69,6 +74,8 @@ module Ecoportal
|
|
69
74
|
# no chance you can avoid invinite loop for `get_key` without setting an
|
70
75
|
# instance variable key at the moment of the object creation, when the
|
71
76
|
# `doc` is firstly received
|
77
|
+
# @param method [Symbol] the method that exposes the value
|
78
|
+
# as well as its `key` in the underlying `Hash` model.
|
72
79
|
def passkey(method)
|
73
80
|
method = method.to_s.freeze
|
74
81
|
var = instance_variable_name(method)
|
@@ -90,7 +97,33 @@ module Ecoportal
|
|
90
97
|
self
|
91
98
|
end
|
92
99
|
|
100
|
+
# These are methods that should always be present in patch update
|
101
|
+
# @note
|
102
|
+
# - `DoubleModel` can be used with objects that do not use `patch_ver`
|
103
|
+
# - This ensures that does that do, will get the correct patch update model
|
104
|
+
# @param method [Symbol] the method that exposes the value
|
105
|
+
# as well as its `key` in the underlying `Hash` model.
|
106
|
+
# @param default [Value] the default value that
|
107
|
+
# this `key` will be written in the model when it doesn't exixt
|
108
|
+
def passforced(method, default: , read_only: false)
|
109
|
+
model_forced_keys[method.to_s.freeze] = default
|
110
|
+
passthrough(method, read_only: read_only)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Ensures `doc` has the `model_forced_keys`. If it doesn't, it adds those missing
|
114
|
+
# with the defined `default` values
|
115
|
+
def enforce!(doc)
|
116
|
+
return unless doc && doc.is_a?(Hash)
|
117
|
+
return if model_forced_keys.empty?
|
118
|
+
model_forced_keys.each do |key, default|
|
119
|
+
doc[key] = default unless doc.key?(key)
|
120
|
+
end
|
121
|
+
doc
|
122
|
+
end
|
123
|
+
|
93
124
|
# Same as `attr_accessor` but links to a subjacent `Hash` model property
|
125
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
126
|
+
# as well as its `key` in the underlying `Hash` model.
|
94
127
|
# @param read_only [Boolean] should it only define the reader?
|
95
128
|
def passthrough(*methods, read_only: false)
|
96
129
|
pass_reader *methods
|
@@ -100,6 +133,8 @@ module Ecoportal
|
|
100
133
|
|
101
134
|
# To link as a `Time` date to a subjacent `Hash` model property
|
102
135
|
# @see Ecoportal::API::Common::Content::DoubleModel#passthrough
|
136
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
137
|
+
# as well as its `key` in the underlying `Hash` model.
|
103
138
|
# @param read_only [Boolean] should it only define the reader?
|
104
139
|
def passdate(*methods, read_only: false)
|
105
140
|
pass_reader(*methods) {|value| to_time(value)}
|
@@ -109,7 +144,21 @@ module Ecoportal
|
|
109
144
|
self
|
110
145
|
end
|
111
146
|
|
147
|
+
# To link as a `Boolean` to a subjacent `Hash` model property
|
148
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
149
|
+
# as well as its `key` in the underlying `Hash` model.
|
150
|
+
# @param read_only [Boolean] should it only define the reader?
|
151
|
+
def passboolean(*methods, read_only: false)
|
152
|
+
pass_reader(*methods) {|value| value}
|
153
|
+
unless read_only
|
154
|
+
pass_writer(*methods) {|value| !!value}
|
155
|
+
end
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
112
159
|
# To link as plain `Array` to a subjacent `Hash` model property
|
160
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
161
|
+
# as well as its `key` in the underlying `Hash` model.
|
113
162
|
# @param order_matters [Boolean] does the order matter
|
114
163
|
# @param uniq [Boolean] should it contain unique elements
|
115
164
|
def passarray(*methods, order_matters: true, uniq: true)
|
@@ -131,6 +180,10 @@ module Ecoportal
|
|
131
180
|
end
|
132
181
|
|
133
182
|
# Helper to embed one nested object under one property
|
183
|
+
# @param method [Symbol] the method that exposes the embeded object
|
184
|
+
# @param key [Symbol] the `key` that embeds it to the underlying `Hash` model
|
185
|
+
# @nullable [Boolean] to specify if this object can be `nil`
|
186
|
+
# @param klass [Class, String] the class of the embedded object
|
134
187
|
def embeds_one(method, key: method, nullable: false, klass:)
|
135
188
|
embed(method, key: key, nullable: nullable, multiple: false, klass: klass)
|
136
189
|
end
|
@@ -138,7 +191,11 @@ module Ecoportal
|
|
138
191
|
# @note
|
139
192
|
# - if you have a dedicated `Enumerable` class to manage `many`, you should use `:enum_class`
|
140
193
|
# - otherwise, just indicate the child class in `:klass` and it will auto generate the class
|
141
|
-
# @param
|
194
|
+
# @param method [Symbol] the method that exposes the embeded object
|
195
|
+
# @param key [Symbol] the `key` that embeds it to the underlying `Hash` model
|
196
|
+
# @param order_matters [Boolean] to state if the order will matter
|
197
|
+
# @param klass [Class, String] the class of the individual elements it embeds
|
198
|
+
# @param enum_class [Class, String] the class of the collection that will hold the individual elements
|
142
199
|
def embeds_many(method, key: method, order_matters: false, order_key: nil, klass: nil, enum_class: nil)
|
143
200
|
if enum_class
|
144
201
|
eclass = enum_class
|
@@ -151,7 +208,7 @@ module Ecoportal
|
|
151
208
|
else
|
152
209
|
raise "You should either specify the 'klass' of the elements or the 'enum_class'"
|
153
210
|
end
|
154
|
-
embed(method, key: key, multiple: true, klass: eclass)
|
211
|
+
embed(method, key: key, multiple: true, klass: eclass)
|
155
212
|
end
|
156
213
|
|
157
214
|
private
|
@@ -175,8 +232,15 @@ module Ecoportal
|
|
175
232
|
end
|
176
233
|
end
|
177
234
|
|
235
|
+
# The list of keys that will be forced in the model
|
236
|
+
def model_forced_keys
|
237
|
+
@forced_model_keys ||= {}
|
238
|
+
end
|
239
|
+
|
178
240
|
end
|
179
241
|
|
242
|
+
inheritable_class_vars :forced_model_keys
|
243
|
+
|
180
244
|
attr_reader :_parent, :_key
|
181
245
|
|
182
246
|
def initialize(doc = {}, parent: self, key: nil)
|
@@ -184,6 +248,8 @@ module Ecoportal
|
|
184
248
|
@_parent = parent || self
|
185
249
|
@_key = key || self
|
186
250
|
|
251
|
+
self.class.enforce!(doc)
|
252
|
+
|
187
253
|
if _parent == self
|
188
254
|
@doc = doc
|
189
255
|
@original_doc = JSON.parse(@doc.to_json)
|
@@ -200,11 +266,13 @@ module Ecoportal
|
|
200
266
|
_parent.root
|
201
267
|
end
|
202
268
|
|
269
|
+
# @return [String] the `value` of the `key` method (i.e. `id` value)
|
203
270
|
def key
|
204
271
|
raise "No key_method defined for #{self.class}" unless key_method?
|
205
272
|
self.method(key_method).call
|
206
273
|
end
|
207
274
|
|
275
|
+
# @param [String] the `value` of the `key` method (i.e. `id` value)
|
208
276
|
def key=(value)
|
209
277
|
raise "No key_method defined for #{self.class}" unless key_method?
|
210
278
|
method = "#{key_method}="
|
@@ -223,16 +291,25 @@ module Ecoportal
|
|
223
291
|
end
|
224
292
|
end
|
225
293
|
|
294
|
+
# @return [nil, Hash] the underlying `Hash` model as is (carrying current changes)
|
226
295
|
def doc
|
227
296
|
raise UnlinkedModel.new(from: "#{self.class}#doc", key: _key) unless linked?
|
228
|
-
|
229
|
-
|
297
|
+
if is_root?
|
298
|
+
@doc
|
299
|
+
else
|
300
|
+
_parent.doc.dig(*[_doc_key(_key)].flatten)
|
301
|
+
end
|
230
302
|
end
|
231
303
|
|
304
|
+
# The `original_doc` holds the model as is now on server-side.
|
305
|
+
# @return [nil, Hash] the underlying `Hash` model as after last `consolidate!` changes
|
232
306
|
def original_doc
|
233
307
|
raise UnlinkedModel.new(from: "#{self.class}#original_doc", key: _key) unless linked?
|
234
|
-
|
235
|
-
|
308
|
+
if is_root?
|
309
|
+
@original_doc
|
310
|
+
else
|
311
|
+
_parent.original_doc.dig(*[_doc_key(_key)].flatten)
|
312
|
+
end
|
236
313
|
end
|
237
314
|
|
238
315
|
def as_json
|
@@ -243,25 +320,37 @@ module Ecoportal
|
|
243
320
|
doc.to_json(*args)
|
244
321
|
end
|
245
322
|
|
323
|
+
# @return [nil, Hash] the patch `Hash` model including only the changes between
|
324
|
+
# `original_doc` and `doc`
|
246
325
|
def as_update
|
247
326
|
new_doc = as_json
|
248
327
|
Common::Content::HashDiffPatch.patch_diff(new_doc, original_doc)
|
249
328
|
end
|
250
329
|
|
330
|
+
# @return [Boolean] stating if there are changes
|
251
331
|
def dirty?
|
252
332
|
as_update != {}
|
253
333
|
end
|
254
334
|
|
335
|
+
# It makes `original_doc` to be like `doc`
|
336
|
+
# @note
|
337
|
+
# - after executing it, there will be no pending changes
|
338
|
+
# - you should technically run this command, after a successful update request to the server
|
255
339
|
def consolidate!
|
256
340
|
replace_original_doc(JSON.parse(doc.to_json))
|
257
341
|
end
|
258
342
|
|
343
|
+
# It makes `doc` to be like `original`
|
344
|
+
# @note
|
345
|
+
# - after executing it, changes in `doc` will be lost
|
346
|
+
# - you should technically run this command only if you want to remove certain changes
|
347
|
+
# @key [Symbol] the specific part of the model you want to `reset`
|
259
348
|
def reset!(key = nil)
|
260
349
|
if key
|
261
|
-
keys = [].
|
350
|
+
keys = [key].flatten.compact
|
262
351
|
odoc = original_doc.dig(*keys)
|
263
|
-
|
264
|
-
|
352
|
+
odoc = odoc && JSON.parse(odoc.to_json)
|
353
|
+
dig_set(doc, keys, odoc)
|
265
354
|
else
|
266
355
|
replace_doc(JSON.parse(original_doc.to_json))
|
267
356
|
end
|