scheming 0.3.0 → 0.5.0

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: bc01781074d4363c7a93440ca775680ad40e390eadf0dd84501501f96aad242f
4
- data.tar.gz: c5356c5b7beb9d74f6489db0d4024973755fc5c2b6a5c015a97d4b21d612191c
3
+ metadata.gz: b21c99fc59c9fe7da35644b47be93b2d6bba2f13f4ef814008a64c92f2235323
4
+ data.tar.gz: c0ff8026a852f0b8e4c91bf86aa4a172502a12b3c89dcd693527863dc7cf58aa
5
5
  SHA512:
6
- metadata.gz: d5ebcaf385cbf2148e37d326c06bd49bd6aa584c9d419096dbb8a7e5f909c191c93b1bc1a294c2a4589c9bf2a9902bf775d73679c440134ebae600ce25e9f110
7
- data.tar.gz: 169ff09cbed7450f5d22754db231e98b5752d98fc00b8dfd2613cb0f0054c59efa24e4b8e86331b32823e76341de46685b8a45abda5416396cdd3b81f8809890
6
+ metadata.gz: 93fa8e2cd04de2c77495754fe04aa2cbd84070a862835c83ef535a7830b6e41337b401f2e35dbf297434397523e24b50c8cb97063745fe58d61f881114187424
7
+ data.tar.gz: 61c3cf8462b6d9075e593d00fa76921bbb7958e1ac2590f2a4683ff5c2aeac40b28209e579270eff279cea0261d6d1ea8194a0a87d2ebd3b56f93f8bfc8a2966
data/CHANGELOG.md CHANGED
@@ -1,14 +1,39 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2024-04-26
3
+ ## [0.5.0] - 2024-05-02
4
4
 
5
- - Initial release
5
+ ### Added
6
6
 
7
- ## [0.2.0] - 2024-05-01
7
+ - Support for `generic` definitions
8
8
 
9
- ### Added
9
+ # Example
10
+ ```ruby
11
+ Point = Scheming.generic do |(type)|
12
+ Object(x: type, y: type)
13
+ end
10
14
 
11
- - Support for `optional` fields
15
+ Scheming::Schema.json(Point)
16
+ # =>
17
+ {
18
+ type: 'object',
19
+ additionalProperties: false,
20
+ required: %i[x y],
21
+ properties: {
22
+ x: { type: 'number' },
23
+ y: { type: 'number' }
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## [0.4.0] - 2024-05-02
29
+
30
+ ### Breaking Change
31
+
32
+ - Opting for a `tag` system to work with attributes instead
33
+ of a blanket lexical scope like `optional` to work with
34
+ attributes. The long term goal is to expand out the tagging
35
+ system so that it can support much more than we can
36
+ anticipate today.
12
37
 
13
38
  # Example:
14
39
  ```ruby
@@ -18,12 +43,12 @@
18
43
  attribute :taxable, :bool
19
44
  attribute :price, Float
20
45
 
21
- optional
22
-
46
+ tag(:optional)
23
47
  attribute :desc, Nullable(String)
48
+
49
+ tag(:optional)
24
50
  attribute :item_type, Enum('entertainment', 'staple')
25
51
  end
26
- ```
27
52
 
28
53
  ## [0.3.0] - 2024-05-01
29
54
 
@@ -36,3 +61,28 @@
36
61
  ### Enhancement
37
62
 
38
63
  - Ensure all types produce valid JSON Schema
64
+
65
+ ## [0.2.0] - 2024-05-01
66
+
67
+ ### Added
68
+
69
+ - Support for `optional` fields
70
+
71
+ # Example:
72
+ ```ruby
73
+ LineItem = Scheming.object do
74
+ attribute :id, Integer
75
+ attribute :name, String
76
+ attribute :taxable, :bool
77
+ attribute :price, Float
78
+
79
+ optional
80
+
81
+ attribute :desc, Nullable(String)
82
+ attribute :item_type, Enum('entertainment', 'staple')
83
+ end
84
+ ```
85
+
86
+ ## [0.1.0] - 2024-04-26
87
+
88
+ - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scheming (0.3.0)
4
+ scheming (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -20,15 +20,21 @@ LineItem = Scheming.object do
20
20
  attribute :taxable, :bool
21
21
  attribute :price, Float
22
22
 
23
- optional
24
-
23
+ tag(:optional)
25
24
  attribute :desc, Nullable(String)
25
+
26
+ tag(:optional)
26
27
  attribute :item_type, Enum('entertainment', 'staple')
27
28
  end
28
29
 
30
+ Point = Scheming.generic do |(type)|
31
+ Object(x: type, y: type)
32
+ end
33
+
29
34
  Receipt = Scheming.object do
30
35
  attribute :line_items, Array(LineItem)
31
36
  attribute :total, Float
37
+ attribute :location, Point[Float]
32
38
  end
33
39
  ```
34
40
 
@@ -39,7 +45,7 @@ Scheming::Schema.json(Receipt)
39
45
  {
40
46
  type: 'object',
41
47
  additionalProperties: false,
42
- required: %i[line_items total],
48
+ required: %i[line_items total location],
43
49
  properties: {
44
50
  line_items: {
45
51
  type: 'array',
@@ -60,12 +66,21 @@ Scheming::Schema.json(Receipt)
60
66
  price: { type: 'number' },
61
67
  item_type: {
62
68
  type: 'string',
63
- enum: ['intertainment', 'staple']
69
+ enum: %w[entertainment staple]
64
70
  }
65
71
  }
66
72
  }
67
73
  },
68
- total: { type: 'number' }
74
+ total: { type: 'number' },
75
+ location: {
76
+ type: 'object',
77
+ additionalProperties: false,
78
+ required: %i[x y],
79
+ properties: {
80
+ x: { type: 'number' },
81
+ y: { type: 'number' }
82
+ }
83
+ }
69
84
  }
70
85
  }
71
86
  ```
@@ -7,7 +7,7 @@ class Scheming::DSL::DataBuilder
7
7
  def initialize(builder = Scheming::Attribute::ListBuilder.new)
8
8
  @builder = builder
9
9
  @resolver = Scheming::DSL::TypeResolver
10
- @required = true
10
+ @tagging = Scheming::DSL::Tagging.new
11
11
  end
12
12
 
13
13
  # @param field_name [Symbol]
@@ -18,14 +18,17 @@ class Scheming::DSL::DataBuilder
18
18
  @builder = @builder.attribute(
19
19
  field_name,
20
20
  type: @resolver.resolve(type_spec),
21
- is_required: @required
21
+ **@tagging.attribute_params
22
22
  )
23
+ @tagging.reset!
23
24
  nil
24
25
  end
25
26
 
26
- # Mark all arrtibutes after this as optional
27
- def optional
28
- @required = false
27
+ # @param name [Symbol]
28
+ # @param args [Hash<Symbol, Object>]
29
+ def tag(name, **args)
30
+ @tagging.tag!(name, args)
31
+ nil
29
32
  end
30
33
 
31
34
  # @return [Class]
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # = Type Resolver
4
+ class Scheming::DSL::Tagging
5
+ # = Attribute Tag
6
+ #
7
+ # Simple representation of a concept
8
+ # that can be used to aid in the
9
+ # creation of an [Scheming::Attribute]
10
+ #
11
+ class Tag
12
+ # @param name [Symbo]
13
+ # @data [Hash<Symbol, Object>]
14
+ def initialize(name, data)
15
+ @name = name
16
+ @data = data
17
+ end
18
+ end
19
+ private_constant :Tag
20
+
21
+ def initialize
22
+ # @type [Hash<Symbol, Tag>]
23
+ @tags = {}
24
+ end
25
+
26
+ # @return [void]
27
+ def reset!
28
+ @tags.clear
29
+ nil
30
+ end
31
+
32
+ # @param taglist [Hash<Symbol, Object>]
33
+ # @param name [Symbol]
34
+ # @return [Tag]
35
+ def tag!(name, data)
36
+ @tags[name] = Tag.new(name, data)
37
+ end
38
+
39
+ def attribute_params
40
+ {
41
+ is_required: missing?(:optional)
42
+ }
43
+ end
44
+
45
+ def missing?(name) = !has?(name)
46
+ def has?(name) = @tags.key?(name)
47
+ end
data/lib/scheming/dsl.rb CHANGED
@@ -8,6 +8,7 @@
8
8
  # who need to know.
9
9
  #
10
10
  module Scheming::DSL
11
+ require_relative 'dsl/tagging'
11
12
  require_relative 'dsl/type_specs'
12
13
  require_relative 'dsl/data_builder'
13
14
  require_relative 'dsl/object_type_def'
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # = Generic
4
+ #
5
+ # Many types can be "templated" in a way where
6
+ # some types get swapped in and out. Perhaps
7
+ # the most common example for this is with a
8
+ # two dimensional `Point` structure. We could
9
+ # have a point with `Float` coordinates OR they
10
+ # could also be `Integer`:
11
+ #
12
+ # ```ruby
13
+ # Object(x: Float, y: Float)
14
+ # Object(x: Integer, y: Integer)
15
+ # ```
16
+ #
17
+ # Instead of having two defintions we can have
18
+ # a single generic that defins both:
19
+ #
20
+ # ```ruby
21
+ # Point = Scheming::Generic.new do |(t)|
22
+ # Object(x: t, y: t)
23
+ # end
24
+ #
25
+ # Point[Float]
26
+ #
27
+ # Point[Integer]
28
+ # ```
29
+ #
30
+ class Scheming::Generic
31
+ def initialize(&proto_type)
32
+ @proto_type = proto_type
33
+ end
34
+
35
+ # @param types [Scheming::Type::Base]
36
+ def [](*types)
37
+ Scheming::DSL::DataBuilder
38
+ .new
39
+ .instance_exec(types, &@proto_type)
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Scheming
4
- VERSION = '0.3.0'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/scheming.rb CHANGED
@@ -10,6 +10,7 @@ module Scheming
10
10
  require_relative 'scheming/attribute'
11
11
  require_relative 'scheming/type'
12
12
  require_relative 'scheming/schema'
13
+ require_relative 'scheming/generic'
13
14
  require_relative 'scheming/dsl'
14
15
 
15
16
  # @return [Class]
@@ -18,4 +19,7 @@ module Scheming
18
19
  builder.instance_exec(&)
19
20
  builder.build
20
21
  end
22
+
23
+ # @return [Scheming::Generic]
24
+ def self.generic(&) = Scheming::Generic.new(&)
21
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scheming
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Falk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-01 00:00:00.000000000 Z
11
+ date: 2024-05-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ergonomic Data Design for the Masses
14
14
  email:
@@ -32,8 +32,10 @@ files:
32
32
  - lib/scheming/dsl.rb
33
33
  - lib/scheming/dsl/data_builder.rb
34
34
  - lib/scheming/dsl/object_type_def.rb
35
+ - lib/scheming/dsl/tagging.rb
35
36
  - lib/scheming/dsl/type_resolver.rb
36
37
  - lib/scheming/dsl/type_specs.rb
38
+ - lib/scheming/generic.rb
37
39
  - lib/scheming/schema.rb
38
40
  - lib/scheming/schema/json.rb
39
41
  - lib/scheming/type.rb