ecoportal-api-oozes 0.5.5

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +55 -0
  5. data/.travis.yml +5 -0
  6. data/.yardopts +10 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE +21 -0
  9. data/README.md +20 -0
  10. data/Rakefile +27 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/ecoportal-api-oozes.gemspec +31 -0
  14. data/lib/ecoportal/api-oozes.rb +10 -0
  15. data/lib/ecoportal/api/common.rb +18 -0
  16. data/lib/ecoportal/api/common/content.rb +18 -0
  17. data/lib/ecoportal/api/common/content/array_model.rb +287 -0
  18. data/lib/ecoportal/api/common/content/class_helpers.rb +111 -0
  19. data/lib/ecoportal/api/common/content/client.rb +40 -0
  20. data/lib/ecoportal/api/common/content/collection_model.rb +223 -0
  21. data/lib/ecoportal/api/common/content/doc_helpers.rb +67 -0
  22. data/lib/ecoportal/api/common/content/double_model.rb +334 -0
  23. data/lib/ecoportal/api/common/content/hash_diff_patch.rb +162 -0
  24. data/lib/ecoportal/api/common/content/string_digest.rb +22 -0
  25. data/lib/ecoportal/api/common/content/wrapped_response.rb +42 -0
  26. data/lib/ecoportal/api/v2.rb +48 -0
  27. data/lib/ecoportal/api/v2/page.rb +30 -0
  28. data/lib/ecoportal/api/v2/page/component.rb +105 -0
  29. data/lib/ecoportal/api/v2/page/component/action.rb +17 -0
  30. data/lib/ecoportal/api/v2/page/component/action_field.rb +16 -0
  31. data/lib/ecoportal/api/v2/page/component/checklist_field.rb +16 -0
  32. data/lib/ecoportal/api/v2/page/component/checklist_item.rb +15 -0
  33. data/lib/ecoportal/api/v2/page/component/date_field.rb +13 -0
  34. data/lib/ecoportal/api/v2/page/component/file.rb +16 -0
  35. data/lib/ecoportal/api/v2/page/component/files_field.rb +14 -0
  36. data/lib/ecoportal/api/v2/page/component/gauge_field.rb +13 -0
  37. data/lib/ecoportal/api/v2/page/component/geo_field.rb +13 -0
  38. data/lib/ecoportal/api/v2/page/component/image.rb +16 -0
  39. data/lib/ecoportal/api/v2/page/component/images_field.rb +14 -0
  40. data/lib/ecoportal/api/v2/page/component/law_field.rb +12 -0
  41. data/lib/ecoportal/api/v2/page/component/number_field.rb +12 -0
  42. data/lib/ecoportal/api/v2/page/component/people_field.rb +13 -0
  43. data/lib/ecoportal/api/v2/page/component/plain_text_field.rb +13 -0
  44. data/lib/ecoportal/api/v2/page/component/reference_field.rb +12 -0
  45. data/lib/ecoportal/api/v2/page/component/rich_text_field.rb +13 -0
  46. data/lib/ecoportal/api/v2/page/component/selection_field.rb +18 -0
  47. data/lib/ecoportal/api/v2/page/component/selection_option.rb +15 -0
  48. data/lib/ecoportal/api/v2/page/component/signature_field.rb +14 -0
  49. data/lib/ecoportal/api/v2/page/component/tag_field.rb +12 -0
  50. data/lib/ecoportal/api/v2/page/components.rb +20 -0
  51. data/lib/ecoportal/api/v2/page/section.rb +36 -0
  52. data/lib/ecoportal/api/v2/page/sections.rb +14 -0
  53. data/lib/ecoportal/api/v2/page/stage.rb +16 -0
  54. data/lib/ecoportal/api/v2/page/stages.rb +14 -0
  55. data/lib/ecoportal/api/v2/pages.rb +63 -0
  56. data/lib/ecoportal/api/v2/register.rb +36 -0
  57. data/lib/ecoportal/api/v2/registers.rb +35 -0
  58. data/lib/ecoportal/api/v2/template.rb +10 -0
  59. data/lib/ecoportal/api/v2/version.rb +7 -0
  60. metadata +219 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f6ecefc83d30f273a4ededb781765cde494d5e6e0facad8a501fc6ef023e73ee
4
+ data.tar.gz: b1e0b4dab879d237580bb4d599ea500fe7a5154f6f7f874e418360bfefc9700d
5
+ SHA512:
6
+ metadata.gz: 98694b883b97f35fc71c0633717d92ec9da2704bd6d63c824a38c43eca512645ab6f3ecd77924d41ae527d112ffc36fcc4190f82e06b4b6453d21ccca44de22d
7
+ data.tar.gz: 9ef14de17795590c48d3b3cb0a6e2ba96be3b1d1ff76cee959a1860cbf1689d17b0551842352b7326094d1c8071a8569cf58c6b8feb5dd8933da8cd6a69521fc
@@ -0,0 +1,20 @@
1
+ # it's a gem, ignore the lockfile
2
+ Gemfile.lock
3
+
4
+ # build artifacts
5
+ *.gem
6
+ /.bundle/
7
+ /vendor/bundle
8
+ /spec/reports/
9
+ /tmp/
10
+ /pkg/
11
+
12
+ # docs
13
+ /.yardoc
14
+ /_yardoc/
15
+ /coverage/
16
+ /doc/
17
+
18
+ # rspec failure tracking
19
+ .rspec_status
20
+ scratch.rb
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,55 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5.1
3
+ Exclude:
4
+ - 'config/routes.rb'
5
+
6
+ Metrics/LineLength:
7
+ Enabled: false
8
+ Metrics/BlockLength:
9
+ ExcludedMethods: [context, describe]
10
+ Max: 50
11
+ Metrics/MethodLength:
12
+ Max: 50
13
+ Metrics/ClassLength:
14
+ Max: 200
15
+ Metrics/AbcSize:
16
+ Max: 30
17
+
18
+ ParameterLists:
19
+ Max: 5
20
+ CountKeywordArgs: false
21
+
22
+ Style/StringLiterals:
23
+ Enabled: false
24
+ Style/FrozenStringLiteralComment:
25
+ Enabled: false
26
+ Style/CommentedKeyword:
27
+ Enabled: false
28
+ Style/MultilineBlockChain:
29
+ Enabled: false
30
+ Style/Documentation:
31
+ Enabled: false
32
+ Style/StringLiteralsInInterpolation:
33
+ Enabled: false
34
+ Style/AndOr:
35
+ Enabled: false
36
+
37
+ Layout/SpaceInsideHashLiteralBraces:
38
+ Enabled: false
39
+ Layout/SpaceInsideBlockBraces:
40
+ Enabled: false
41
+ Layout/SpaceAroundOperators:
42
+ Enabled: false
43
+ Layout/ExtraSpacing:
44
+ AllowForAlignment: true
45
+ Layout/AccessModifierIndentation:
46
+ EnforcedStyle: indent
47
+ Layout/DotPosition:
48
+ EnforcedStyle: trailing
49
+ Layout/MultilineMethodCallIndentation:
50
+ EnforcedStyle: indented
51
+ Layout/IndentHash:
52
+ Enabled: false
53
+
54
+ Naming/VariableNumber:
55
+ EnforcedStyle: snake_case
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ before_install: gem install bundler -v 1.16.1
@@ -0,0 +1,10 @@
1
+ --readme README.md
2
+ --charset utf-8
3
+ --markup-provider=redcarpet
4
+ --markup=markdown
5
+ --no-private
6
+ --output-dir ./doc
7
+ 'lib/**/*.rb'
8
+ -
9
+ CHANGELOG.md
10
+ LICENSE
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ecoportal-api.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 ecoPortal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,20 @@
1
+ # Ecoportal::API::V2
2
+
3
+ This is a basic collection of helpers that can be used to interact with the
4
+ [ecoPortal](https://www.ecoportal.com) `APIv2`
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'ecoportal-api-oozes', require: %w[ecoportal/api-oozes]
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install ecoportal-api-oozes
@@ -0,0 +1,27 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "yard"
4
+ require "redcarpet"
5
+
6
+ desc "run the specs"
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ desc "run rspec showing backtrace"
10
+ RSpec::Core::RakeTask.new(:spec_trace) do |task|
11
+ task.rspec_opts = ['--backtrace']
12
+ end
13
+
14
+ desc "run rspec stopping on first fail, and show backtrace"
15
+ RSpec::Core::RakeTask.new(:spec_fast) do |task|
16
+ task.rspec_opts = ['--fail-fast', '--backtrace']
17
+ end
18
+
19
+ # default task name is yard
20
+ desc "Yard: generate all the documentation"
21
+ YARD::Rake::YardocTask.new(:doc) do |t|
22
+ #t.files = ['lib/**/*.rb']
23
+ end
24
+
25
+ task :default => [:spec]
26
+ task :rspec_trace => :spec_trace
27
+ task :rspec_fast => :spec_fast
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ecoportal/api"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "pry"
14
+ Pry.start(__FILE__)
@@ -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,31 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ecoportal/api/v2/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ecoportal-api-oozes"
8
+ spec.version = Ecoportal::API::V2::VERSION
9
+ spec.authors = ["Oscar Segura"]
10
+ spec.email = ["rien@ecoportal.co.nz", "oscar@ecoportal.co.nz", "bozydar@ecoportal.co.nz"]
11
+
12
+ spec.summary = %q{A collection of helpers for interacting with the ecoPortal MS's V2 API}
13
+ spec.homepage = "https://www.ecoportal.com"
14
+ spec.licenses = %w[MIT]
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 2.1"
24
+ spec.add_development_dependency "rake", "~> 12.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "yard", "~> 0.9", ">= 0.9.18"
27
+ spec.add_development_dependency "redcarpet", "~> 3.5", ">= 3.5.0"
28
+ spec.add_development_dependency "pry"
29
+
30
+ spec.add_dependency 'ecoportal-api', '~> 0.5', '>= 0.5.5'
31
+ end
@@ -0,0 +1,10 @@
1
+ require "ecoportal/api"
2
+ require "ecoportal/api/v2/version"
3
+
4
+ module Ecoportal
5
+ module API
6
+ end
7
+ end
8
+
9
+ require "ecoportal/api/common"
10
+ require "ecoportal/api/v2"
@@ -0,0 +1,18 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'ecoportal/api/common/base_class'
9
+ require 'ecoportal/api/common/hash_diff'
10
+ require 'ecoportal/api/common/base_model'
11
+ require 'ecoportal/api/common/doc_helpers'
12
+ require 'ecoportal/api/common/logging'
13
+ require 'ecoportal/api/common/client'
14
+ require 'ecoportal/api/common/response'
15
+ require 'ecoportal/api/common/wrapped_response'
16
+ require 'ecoportal/api/common/batch_response'
17
+ require 'ecoportal/api/common/batch_operation'
18
+ require 'ecoportal/api/common/content'
@@ -0,0 +1,18 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ module Content
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require 'ecoportal/api/common/content/class_helpers'
11
+ require 'ecoportal/api/common/content/string_digest'
12
+ require 'ecoportal/api/common/content/double_model'
13
+ require 'ecoportal/api/common/content/array_model'
14
+ require 'ecoportal/api/common/content/collection_model'
15
+ require 'ecoportal/api/common/content/doc_helpers'
16
+ require 'ecoportal/api/common/content/hash_diff_patch'
17
+ require 'ecoportal/api/common/content/client'
18
+ require 'ecoportal/api/common/content/wrapped_response'
@@ -0,0 +1,287 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ module Content
5
+ # Class to handle a plain Array embedded in a Hashed model.
6
+ # @note its purpose is to handle an Array of basic objects (i.e. `Date`, `String`, `Number`)
7
+ class ArrayModel < Content::DoubleModel
8
+ class TypeMismatchedComparison < Exception
9
+ def initialize (this: nil, that: msg = "Trying to compare objects with different behavior.")
10
+ if this
11
+ msg += " From object with 'order_matters: #{this.order_matters?}' and 'uniq: #{this.uniq?}'."
12
+ end
13
+ if that
14
+ msg += " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'."
15
+ end
16
+ super(msg)
17
+ end
18
+ end
19
+
20
+ include Enumerable
21
+
22
+ class << self
23
+ attr_accessor :order_matters, :uniq
24
+
25
+ # @param a [ArrayModel]
26
+ # @param b [ArrayModel]
27
+ # @return [Boolean] `true` if both elements have same behaviour
28
+ def same_type?(a, b)
29
+ raise "To use this comparison both objects should be `ArrayModel`" unless a.is_a?(ArrayModel) && b.is_a?(ArrayModel)
30
+ (a.order_matters? == b.order_matters?) && (a.uniq? == b.uniq?)
31
+ end
32
+
33
+ end
34
+
35
+ def initialize(doc = {}, parent: self, key: nil)
36
+ super(doc, parent: parent, key: key)
37
+ end
38
+
39
+ def order_matters?; self.class.order_matters; end
40
+ def uniq?; self.class.uniq; end
41
+
42
+ def length; count; end
43
+ def empty?; count == 0; end
44
+ def present?; count > 0; end
45
+
46
+ def each(&block)
47
+ return to_enum(:each) unless block
48
+ _items.each(&block)
49
+ end
50
+
51
+ # @return [Array] the array element represented by this object
52
+ def _items
53
+ replace_doc([]) unless doc.is_a?(Array)
54
+ doc.tap {|d| d.uniq! if uniq?}
55
+ end
56
+
57
+ # @see #_items
58
+ # @return [Array] a **copy** of the `Array` elements
59
+ def to_a
60
+ _items.slice(0..-1)
61
+ end
62
+
63
+ # @param value [Object, Array<Object>, ArrayModel] the value(s) of the new object
64
+ # @return [ArrayModel] a new object with the current class
65
+ def new_from(value)
66
+ self.class.new(into_a(value))
67
+ end
68
+
69
+ # @return [ArrayModel] a copy of the current object
70
+ def dup
71
+ new_from(to_a)
72
+ end
73
+
74
+ # @return [Integer] the position of the element in the `Array`
75
+ def index(value)
76
+ _items.index(value)
77
+ end
78
+
79
+ # Retrieves the element of a certain position
80
+ # @param pos [Integer] the position of the element
81
+ # @return [Date, String, Number]
82
+ def [](pos)
83
+ _items[pos]
84
+ end
85
+
86
+ # Sets the element of a certain position
87
+ # @param pos [Integer] the position of the element
88
+ # @param value [String, Date, Number] the element
89
+ # @return [Date, String, Number]
90
+ def []=(post, value)
91
+ _items[pos] = value
92
+ on_change
93
+ self[pos]
94
+ end
95
+
96
+ # Compares with an `Array` or another `ArrayModel`
97
+ # @param a [ArrayModel, Array]
98
+ def ==(a)
99
+ return true if self.equal?(a)
100
+ return false unless (a.class == self.class) || a.is_a?(Array)
101
+ case a
102
+ when Array
103
+ self == new_from(a)
104
+ when ArrayModel
105
+ return true if
106
+ raise TypeMismatchedComparison.new(this: self, that: a) unless self.class.same_type?(self, a)
107
+
108
+ if self.order_matters?
109
+ _items == a.to_a
110
+ else
111
+ (_items - a.to_a).empty? && (a.to_a - _items).empty?
112
+ end
113
+ end
114
+ end
115
+
116
+ # @return [Boolean] `true` if `value` is present, `false` otherwise
117
+ def include?(value)
118
+ _items.include?(value)
119
+ end
120
+
121
+ def include_any?(*value)
122
+ value.any? {|v| _items.include?(v)}
123
+ end
124
+
125
+ def include_all?(*value)
126
+ value.all? {|v| _items.include?(v)}
127
+ end
128
+
129
+ # Adds an element to the subjacent `Array`
130
+ # @note if the class variable `uniq` is `true`, it skips duplicates
131
+ def <<(value)
132
+ _items.concat(into_a(value)).tap do |doc|
133
+ doc.uniq! if uniq?
134
+ end
135
+ on_change
136
+ self
137
+ end
138
+
139
+ # @see #<<
140
+ def push!(value)
141
+ self << value
142
+ end
143
+
144
+ # @see #<<
145
+ # @note same as #push! but for multiple elements
146
+ def concat!(values)
147
+ self << values
148
+ end
149
+
150
+ # Resets the `Array` by keeping its reference and adds the value(s)
151
+ # @param value [Object, Array<Object>, ArrayModel] the value(s) to be added
152
+ # @param values [Array]
153
+ def <(values)
154
+ _items.clear
155
+ self << values
156
+ end
157
+
158
+ # Clears the `Array` keeping its reference
159
+ def clear!
160
+ _items.clear
161
+ on_change
162
+ self
163
+ end
164
+
165
+ # Concat to new
166
+ def +(value)
167
+ new_from(self.to_a + into_a(value))
168
+ end
169
+
170
+ # Join
171
+ # @param value [Object, Array<Object>, ArrayModel] the value(s) to be joined
172
+ # @return [ArrayModel] a new object instance with the intersection done
173
+ def |(value)
174
+ new = new_from(value) - self
175
+ new_from(to_a + new.to_a)
176
+ end
177
+
178
+ # Intersect
179
+ # @param value [Object, Array<Object>, ArrayModel] the value(s) to be deleted
180
+ # @return [ArrayModel] a new object instance with the intersection done
181
+ def &(value)
182
+ self.dup.tap do |out|
183
+ self.dup.tap do |delta|
184
+ delta.delete!(*into_a(value))
185
+ out.delete!(*into_a(delta))
186
+ end
187
+ end
188
+ end
189
+
190
+ # Subtract
191
+ # @param value [Object, Array<Object>, ArrayModel] the value(s) to be deleted
192
+ # @return [ArrayModel] a **copy** of the object with the elements subtracted
193
+ def -(value)
194
+ self.dup.tap do |copy|
195
+ copy.delete!(*into_a(value))
196
+ end
197
+ end
198
+
199
+ # Deletes `values` from the `Array`
200
+ def delete!(*values)
201
+ values.map do |v|
202
+ deletion!(v)
203
+ end.tap do |r|
204
+ on_change
205
+ end
206
+ end
207
+
208
+ # Swaps two values' positions
209
+ # @note this will work with first instances when **not** `uniq?`
210
+ # @param val1 [Object] the first value to swap
211
+ # @param val2 [Object] the second value to swap
212
+ # @return [Integer] the new of `value1`, `nil` if it wasn't moved
213
+ def swap(value1, value2)
214
+ index(value2).tap do |dest|
215
+ if dest && pos = index(value1)
216
+ _items[dest] = value1
217
+ _items[pos] = value2
218
+ end
219
+ end
220
+ end
221
+
222
+ # TODO
223
+ def insert_one(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
224
+ i = index(value)
225
+ return i if (i && uniq?)
226
+
227
+ pos = case
228
+ when used_param?(pos)
229
+ pos
230
+ when used_param?(before)
231
+ index(before)
232
+ when used_param?(after)
233
+ if i = index(after)
234
+ i + 1
235
+ end
236
+ else
237
+ length
238
+ end
239
+
240
+ pos.tap do |i|
241
+ unless !i
242
+ _items.insert(pos, value)
243
+ on_change
244
+ end
245
+ end
246
+ end
247
+
248
+ # TODO
249
+ def move(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
250
+ if i = index(value)
251
+ unless i == pos
252
+
253
+ on_change
254
+ end
255
+ pos
256
+ end
257
+ end
258
+
259
+ protected
260
+
261
+ def on_change
262
+ # to be overriden by child classes
263
+ end
264
+
265
+ private
266
+
267
+ def into_a(value)
268
+ raise "Can't convert to 'Array' a 'Hash', as is a key_value pair Enumerable" if value.is_a?(Hash)
269
+ return value.to_a.slice(0..-1) if value.is_a?(Enumerable)
270
+ [].push(value).compact
271
+ end
272
+
273
+ def deletion!(value)
274
+ if !uniq?
275
+ if i = _items.index(value)
276
+ _items.slice!(i)
277
+ end
278
+ else
279
+ _items.delete(value)
280
+ end
281
+ end
282
+
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end