attributor 6.1 → 6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/lib/attributor/attribute.rb +7 -0
- data/lib/attributor/types/hash.rb +17 -1
- data/lib/attributor/types/model.rb +5 -0
- data/lib/attributor/types/object.rb +12 -2
- data/lib/attributor/version.rb +1 -1
- data/spec/support/objects.rb +2 -0
- data/spec/types/hash_spec.rb +11 -4
- data/spec/types/model_spec.rb +22 -0
- data/spec/types/object_spec.rb +14 -0
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b30fd80bf80e1fba073207107cc6ee008d8f7f5edc3acd49863d58d27c9b2caa
|
4
|
+
data.tar.gz: 7549362dfe5fb7f1eb654ab7927996baee065f4b37cbdb74fcfb472189b8ea17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46fb615c0952564d354ed67e9ed4e794bead86868111cf3a1447f1aab92e9a8106addca135673b59acb67f58dfdbbc5ed8a49d9f5f5cebdf5a2439719c495768
|
7
|
+
data.tar.gz: 726a29e1f6a30025f51a62dfb63fc8331e3202a3553f031ad776679ee7a525a7e689feb75ed184d0eb306b6bbe6b7c03605bb6b396fd5e234e0ddc1fa751b2e8
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
# Attributor Changelog
|
2
2
|
|
3
3
|
## next
|
4
|
-
|
4
|
+
|
5
|
+
## 6.3 (10/21/2022)
|
6
|
+
- Added some small utility enhancements for dealing with attributes and types
|
7
|
+
* .duplicate an attribute, with a different inner type and/or options
|
8
|
+
* .slice a Hash/Model/Struct to reduce the number of keys that it holds
|
9
|
+
* .merge two Hash/Model/Struct keys into an existing one (even if the types differ)
|
10
|
+
|
11
|
+
## 6.2 (5/11/2022)
|
12
|
+
- Added .to_hash for Model/Struct, which returns a symbolized key hash (without recursing). This allows to splat instances of Model/Structs into functions that have keyword arguments.
|
5
13
|
|
6
14
|
## 6.1 (1/7/2022)
|
7
15
|
- added support for enum's out of values in json_schema generation
|
data/lib/attributor/attribute.rb
CHANGED
@@ -45,6 +45,13 @@ module Attributor
|
|
45
45
|
check_options!
|
46
46
|
end
|
47
47
|
|
48
|
+
def duplicate(type: nil, options: nil)
|
49
|
+
clone.tap do |cloned|
|
50
|
+
cloned.instance_variable_set(:@type, type) if type
|
51
|
+
cloned.instance_variable_set(:@options, options) if options
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
48
55
|
def ==(other)
|
49
56
|
raise ArgumentError, "can not compare Attribute with #{other.class.name}" unless other.is_a?(Attribute)
|
50
57
|
|
@@ -41,6 +41,13 @@ module Attributor
|
|
41
41
|
@error = false
|
42
42
|
@requirements = []
|
43
43
|
|
44
|
+
def self.slice!(*keys)
|
45
|
+
missing_keys = keys - @keys.keys
|
46
|
+
raise AttributorException, "Cannot slice! this type, because it does not contain one or more of the requested keys: #{missing_keys}" unless missing_keys.empty?
|
47
|
+
instance_variable_set(:@keys, @keys.slice(*keys))
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
44
51
|
def self.key_type=(key_type)
|
45
52
|
@key_type = Attributor.resolve_type(key_type)
|
46
53
|
@key_attribute = Attribute.new(@key_type)
|
@@ -461,6 +468,7 @@ module Attributor
|
|
461
468
|
else
|
462
469
|
hash[:value] = { type: value_type.describe(true) }
|
463
470
|
hash[:example] = example if example
|
471
|
+
hash[:attributes] = {}
|
464
472
|
end
|
465
473
|
|
466
474
|
hash
|
@@ -567,7 +575,15 @@ module Attributor
|
|
567
575
|
when self.class
|
568
576
|
self.class.new(contents.merge(h.contents))
|
569
577
|
when Attributor::Hash
|
570
|
-
|
578
|
+
source_key_type = self.class.key_type
|
579
|
+
source_value_type = self.class.value_type
|
580
|
+
# Allow merging hashes, but we'll need to coerce keys and/or values if they aren't the same type
|
581
|
+
coerced_contents = h.contents.each_with_object({}) do |(key, val), object|
|
582
|
+
k = (source_key_type && !k.is_a?(source_key_type)) ? source_key_type.load(key) : key
|
583
|
+
v = (source_value_type && !k.is_a?(source_value_type)) ? source_value_type.load(val) : val
|
584
|
+
object[k] = v
|
585
|
+
end
|
586
|
+
self.class.new(contents.merge(coerced_contents))
|
571
587
|
else
|
572
588
|
raise TypeError, "no implicit conversion of #{h.class} into Attributor::Hash"
|
573
589
|
end
|
@@ -179,6 +179,11 @@ module Attributor
|
|
179
179
|
ensure
|
180
180
|
@dumping = false
|
181
181
|
end
|
182
|
+
|
183
|
+
# This allows the splatting of these instances into method calls (top level hash conversion only)
|
184
|
+
def to_hash
|
185
|
+
@contents
|
186
|
+
end
|
182
187
|
end
|
183
188
|
|
184
189
|
# Override the generic way to get a value from an instance (models need to call the method)
|
@@ -13,10 +13,20 @@ module Attributor
|
|
13
13
|
def self.example(_context = nil, options: {})
|
14
14
|
'An Object'
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
|
+
# Not really used (we override as_json_schema to represent this as an Any Type),
|
18
|
+
# but if it _were_ used, this would be accurate.
|
17
19
|
def self.json_schema_type
|
18
|
-
:object
|
20
|
+
:object
|
19
21
|
end
|
20
22
|
|
23
|
+
# Represents Object as an OpenAPI Any Type.
|
24
|
+
#
|
25
|
+
# @see https://swagger.io/docs/specification/data-models/data-types/#any
|
26
|
+
def self.as_json_schema(**kwargs)
|
27
|
+
schema = super(**kwargs)
|
28
|
+
schema.delete(:type)
|
29
|
+
schema
|
30
|
+
end
|
21
31
|
end
|
22
32
|
end
|
data/lib/attributor/version.rb
CHANGED
data/spec/types/hash_spec.rb
CHANGED
@@ -1189,16 +1189,15 @@ describe Attributor::Hash do
|
|
1189
1189
|
end
|
1190
1190
|
|
1191
1191
|
context '#merge' do
|
1192
|
-
let(:hash_of_strings) { Attributor::Hash.of(key: String) }
|
1193
|
-
let(:
|
1192
|
+
let(:hash_of_strings) { Attributor::Hash.of(key: String, value: Integer) }
|
1193
|
+
let(:hash_of_symbols_and_string_vals) { Attributor::Hash.of(key: Symbol) }
|
1194
1194
|
|
1195
1195
|
let(:merger) { hash_of_strings.load({'a' => 1},nil) }
|
1196
1196
|
let(:good_mergee) { hash_of_strings.load({'b' => 2},nil) }
|
1197
|
-
let(:
|
1197
|
+
let(:different_hash_mergee) { hash_of_symbols_and_string_vals.load({c: '3'}) }
|
1198
1198
|
let(:result) { hash_of_strings.load({'a' => 1, 'b' => 2},nil) }
|
1199
1199
|
|
1200
1200
|
it 'validates that the mergee is of like type' do
|
1201
|
-
expect { merger.merge(bad_mergee) }.to raise_error(ArgumentError)
|
1202
1201
|
expect { merger.merge({}) }.to raise_error(TypeError)
|
1203
1202
|
expect { merger.merge(nil) }.to raise_error(TypeError)
|
1204
1203
|
end
|
@@ -1210,6 +1209,14 @@ describe Attributor::Hash do
|
|
1210
1209
|
it 'merges' do
|
1211
1210
|
expect(merger.merge(good_mergee)).to eq(result)
|
1212
1211
|
end
|
1212
|
+
|
1213
|
+
it 'allows Hash merges, even if they come from different types, by coercing keys/values' do
|
1214
|
+
merged = merger.merge(different_hash_mergee)
|
1215
|
+
expect(merged).to be_a(hash_of_strings)
|
1216
|
+
result = hash_of_strings.load({'a' => 1, 'c' => 3},nil)
|
1217
|
+
# :c is coerced to 'c' and values are coerced to integers
|
1218
|
+
expect(merged).to eq(result)
|
1219
|
+
end
|
1213
1220
|
end
|
1214
1221
|
|
1215
1222
|
context Attributor::InvalidDefinition do
|
data/spec/types/model_spec.rb
CHANGED
@@ -523,4 +523,26 @@ describe Attributor::Model do
|
|
523
523
|
expect(example.dump).to eq({})
|
524
524
|
end
|
525
525
|
end
|
526
|
+
|
527
|
+
context '#to_hash' do
|
528
|
+
let(:model_type) do
|
529
|
+
Class.new(Attributor::Model) do
|
530
|
+
attributes do
|
531
|
+
attribute :name, String
|
532
|
+
attribute :subkey do
|
533
|
+
attribute :id, Integer
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
subject { model_type.new(name: 'Praxis', subkey: { id: 1 }).to_hash }
|
540
|
+
it 'returns the top keys as a hash' do
|
541
|
+
expect(subject.keys).to eq([:name, :subkey])
|
542
|
+
end
|
543
|
+
it 'does not recurse down' do
|
544
|
+
expect(subject[:subkey]).to be_kind_of Attributor::Struct
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
526
548
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe Attributor::Object do
|
4
|
+
context 'JSON Schema representation' do
|
5
|
+
subject { UntypedObject.as_json_schema }
|
6
|
+
it 'is an Any Type' do
|
7
|
+
# "A schema without a type matches any data type – numbers, strings, objects, and so on."
|
8
|
+
# c.f. https://swagger.io/docs/specification/data-models/data-types/#any
|
9
|
+
expect(subject).not_to have_key(:type)
|
10
|
+
# but we still preserve Ruby type name, if anyone is curious
|
11
|
+
expect(subject[:"x-type_name"]).to eq("UntypedObject")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attributor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '6.
|
4
|
+
version: '6.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep M. Blanquer
|
8
8
|
- Dane Jensen
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-10-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hashie
|
@@ -291,7 +291,7 @@ dependencies:
|
|
291
291
|
- - ">="
|
292
292
|
- !ruby/object:Gem::Version
|
293
293
|
version: '0'
|
294
|
-
description:
|
294
|
+
description:
|
295
295
|
email:
|
296
296
|
- blanquer@gmail.com
|
297
297
|
- dane.jensen@gmail.com
|
@@ -361,6 +361,7 @@ files:
|
|
361
361
|
- spec/support/hashes.rb
|
362
362
|
- spec/support/integers.rb
|
363
363
|
- spec/support/models.rb
|
364
|
+
- spec/support/objects.rb
|
364
365
|
- spec/support/polymorphics.rb
|
365
366
|
- spec/type_spec.rb
|
366
367
|
- spec/types/bigdecimal_spec.rb
|
@@ -377,6 +378,7 @@ files:
|
|
377
378
|
- spec/types/ids_spec.rb
|
378
379
|
- spec/types/integer_spec.rb
|
379
380
|
- spec/types/model_spec.rb
|
381
|
+
- spec/types/object_spec.rb
|
380
382
|
- spec/types/polymorphic_spec.rb
|
381
383
|
- spec/types/regexp_spec.rb
|
382
384
|
- spec/types/string_spec.rb
|
@@ -390,7 +392,7 @@ homepage: https://github.com/rightscale/attributor
|
|
390
392
|
licenses:
|
391
393
|
- MIT
|
392
394
|
metadata: {}
|
393
|
-
post_install_message:
|
395
|
+
post_install_message:
|
394
396
|
rdoc_options: []
|
395
397
|
require_paths:
|
396
398
|
- lib
|
@@ -406,7 +408,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
406
408
|
version: '0'
|
407
409
|
requirements: []
|
408
410
|
rubygems_version: 3.1.2
|
409
|
-
signing_key:
|
411
|
+
signing_key:
|
410
412
|
specification_version: 4
|
411
413
|
summary: A powerful attribute and type management library for Ruby
|
412
414
|
test_files:
|
@@ -422,6 +424,7 @@ test_files:
|
|
422
424
|
- spec/support/hashes.rb
|
423
425
|
- spec/support/integers.rb
|
424
426
|
- spec/support/models.rb
|
427
|
+
- spec/support/objects.rb
|
425
428
|
- spec/support/polymorphics.rb
|
426
429
|
- spec/type_spec.rb
|
427
430
|
- spec/types/bigdecimal_spec.rb
|
@@ -438,6 +441,7 @@ test_files:
|
|
438
441
|
- spec/types/ids_spec.rb
|
439
442
|
- spec/types/integer_spec.rb
|
440
443
|
- spec/types/model_spec.rb
|
444
|
+
- spec/types/object_spec.rb
|
441
445
|
- spec/types/polymorphic_spec.rb
|
442
446
|
- spec/types/regexp_spec.rb
|
443
447
|
- spec/types/string_spec.rb
|