attributor 6.1 → 6.3

Sign up to get free protection for your applications and to get access to all the features.
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