attributor 6.1 → 6.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a27077cb0a67b6ab8fdde19c88a993ba648c6deb38d5a83766df49b7199338d
4
- data.tar.gz: 99bf9996744d757817fd167fa510b462fab6ee1dd3b52992594d06768966bd53
3
+ metadata.gz: b30fd80bf80e1fba073207107cc6ee008d8f7f5edc3acd49863d58d27c9b2caa
4
+ data.tar.gz: 7549362dfe5fb7f1eb654ab7927996baee065f4b37cbdb74fcfb472189b8ea17
5
5
  SHA512:
6
- metadata.gz: e91ad1a7759be0e56c66f53bafbe6d22f1a2ce724fc777ade2649987d6bf19d184eb0fc5f43d00dcbf2310bbae72359199f34d25c38aa65cc69f38cc28d33a55
7
- data.tar.gz: 947764564827d2d05e967f60ccc100d42eedf219fddab8ffff56bb8f61c0264c67e9bdd77d3a3585b99d80e5e54f22ef2a6e3424c3ba83549df0932874b0c0af
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
- - added support for enum's out of values in json_schema generation
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
@@ -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
- raise ArgumentError, 'cannot merge Attributor::Hash instances of different types' unless h.is_a?(self.class)
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 #FIXME: not sure this is the most appropriate, since an Attributor::Object can be anything
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
@@ -1,3 +1,3 @@
1
1
  module Attributor
2
- VERSION = '6.1'.freeze
2
+ VERSION = '6.3'.freeze
3
3
  end
@@ -0,0 +1,2 @@
1
+ class UntypedObject < Attributor::Object
2
+ end
@@ -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(:hash_of_symbols) { Attributor::Hash.of(key: Symbol) }
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(:bad_mergee) { hash_of_symbols.load({c: 3}) }
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
@@ -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.1'
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-02-07 00:00:00.000000000 Z
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