json_model_rb 0.1.19 → 0.1.20

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: 7b8f164fcb8a5e085028753dd18332a48586deda0a72ad8a41c13c94e7e063b3
4
- data.tar.gz: f544f378a0258a4c6bce6027f2df78f9f7ca2c1c1ca5ff0bbf85baf72f4ae537
3
+ metadata.gz: 98b0c57c0738f93582f7783f5de240050d0129e7015ee2e208101ee2fbf62228
4
+ data.tar.gz: 847d1567156289c42144329ca370250772bdd9fdfa1c4776482d354a51560ab5
5
5
  SHA512:
6
- metadata.gz: 4e670ea581752b7c766d5b2f7baebd9e5b86ced3f53fde695cafb5a633be8b2199830bf4773b44fce050714c3d777763c36616dfa67d99f4248c4dadd352c60e
7
- data.tar.gz: eb8995d23152892fe64ef15556c97b0472dea200dc8dca4e2b94a3ea6a644ffe2319895acaa227c1bbbab2a53dee5521da3a3c0bc98b65aa1c00fcbba2f122d6
6
+ metadata.gz: a8eb301c456c28814b8b7eca3fbbe30a0d7c6e8e789bbc6bbfca73052e0f18934e277913a1cc7632a45fe56245781389bc96ed8d59b01781d63ec08f3c2f0f61
7
+ data.tar.gz: 9ae72f4ab9291f822ed7dcb632744c4b87c8689344fcb3bb68ea469ea605fa57945735af341c1671edcfe2d4b91a8a73ece88fa72c092b9027860f8d1da73d74
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonModel
4
+ module Composeable
5
+ extend(ActiveSupport::Concern)
6
+
7
+ class_methods do
8
+ # @return [Array]
9
+ def composed_types
10
+ @composed_types ||= []
11
+ end
12
+
13
+ # @param [Object] type
14
+ # @param [Symbol] ref_mode
15
+ def compose(type, ref_mode: RefMode::LOCAL)
16
+ composed_types << {
17
+ type: TypeSpec.resolve(type),
18
+ ref_mode: ref_mode,
19
+ }
20
+ end
21
+
22
+ # @return [Array<JsonModel::TypeSpec::Composition>]
23
+ def composed_type_defs
24
+ composed_types.select { |type| type[:ref_mode] == RefMode::LOCAL }.flat_map { |it| it[:type].referenced_schemas }
25
+ end
26
+
27
+ # @return [Array<Hash>]
28
+ def composed_types_as_schema
29
+ composed_types.each_with_object({}) do |it, agg|
30
+ agg.deep_merge!(it[:type].as_schema(ref_mode: it[:ref_mode]))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -3,6 +3,7 @@
3
3
  module JsonModel
4
4
  module Schema
5
5
  extend(ActiveSupport::Concern)
6
+ include(Composeable)
6
7
  include(Properties)
7
8
  include(SchemaMeta)
8
9
 
@@ -61,6 +62,7 @@ module JsonModel
61
62
  required: required_properties_as_schema,
62
63
  '$defs': defs_as_schema,
63
64
  )
65
+ .merge(**composed_types_as_schema)
64
66
  .merge(type: 'object')
65
67
  .compact
66
68
  when RefMode::LOCAL
@@ -94,11 +96,7 @@ module JsonModel
94
96
  end
95
97
 
96
98
  def defs_as_schema
97
- referenced_schemas = local_properties
98
- .values
99
- .flat_map(&:referenced_schemas)
100
- .uniq
101
-
99
+ referenced_schemas = (composed_type_defs + local_properties.values.flat_map(&:referenced_schemas)).uniq
102
100
  if referenced_schemas.any?
103
101
  referenced_schemas.to_h { |type| [type.name.to_sym, type.as_schema] }
104
102
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JsonModel
4
- VERSION = '0.1.19'
4
+ VERSION = '0.1.20'
5
5
  end
data/lib/json_model.rb CHANGED
@@ -5,6 +5,7 @@ require('active_support/concern')
5
5
  require('active_support/core_ext/class/attribute')
6
6
  require('active_support/descendants_tracker')
7
7
  require('uri')
8
+ require('json_model/composeable')
8
9
  require('json_model/config')
9
10
  require('json_model/errors')
10
11
  require('json_model/properties')
@@ -20,15 +20,28 @@ RSpec.describe('User schema') do
20
20
 
21
21
  stub_const('Address', address_class)
22
22
 
23
- user_class = Class.new do
23
+ person_class = Class.new do
24
24
  include(JsonModel::Schema)
25
25
 
26
26
  def self.name
27
- 'User'
27
+ 'Person'
28
28
  end
29
29
 
30
+ schema_id('person.schema.json')
30
31
  property(:name, type: String)
31
32
  property(:email, type: T::String[format: :email])
33
+ end
34
+
35
+ stub_const('Person', person_class)
36
+
37
+ user_class = Class.new do
38
+ include(JsonModel::Schema)
39
+
40
+ def self.name
41
+ 'User'
42
+ end
43
+
44
+ compose(T::AllOf[Person], ref_mode: JsonModel::RefMode::EXTERNAL)
32
45
  property(:age, type: T::Integer[minimum: 0, maximum: 120], optional: true)
33
46
  property(:active, type: T::Boolean, default: true, optional: true)
34
47
  property(:addresses, type: T::Array[Address], ref_mode: JsonModel::RefMode::LOCAL)
@@ -47,9 +60,8 @@ RSpec.describe('User schema') do
47
60
  eq(
48
61
  {
49
62
  type: 'object',
63
+ allOf: [{ '$ref': 'person.schema.json' }],
50
64
  properties: {
51
- name: { type: 'string' },
52
- email: { type: 'string', format: 'email' },
53
65
  age: { type: 'integer', minimum: 0, maximum: 120 },
54
66
  active: { type: 'boolean', default: true },
55
67
  addresses: {
@@ -61,7 +73,7 @@ RSpec.describe('User schema') do
61
73
  websites: { type: 'array', items: { type: 'string', format: 'uri' } },
62
74
  height: { type: 'number' },
63
75
  },
64
- required: %i(addresses email name),
76
+ required: %i(addresses),
65
77
  '$defs': {
66
78
  Address: {
67
79
  type: 'object',
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_model_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.19
4
+ version: 0.1.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gillesberger
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-01-05 00:00:00.000000000 Z
10
+ date: 2026-01-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rake
@@ -103,6 +103,7 @@ files:
103
103
  - LICENSE
104
104
  - README.md
105
105
  - lib/json_model.rb
106
+ - lib/json_model/composeable.rb
106
107
  - lib/json_model/config.rb
107
108
  - lib/json_model/config/options.rb
108
109
  - lib/json_model/errors.rb