verse-schema 1.0.0 → 1.1.0
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/README.md +187 -0
- data/lib/verse/schema/base.rb +1 -1
- data/lib/verse/schema/coalescer/register.rb +1 -1
- data/lib/verse/schema/coalescer.rb +6 -10
- data/lib/verse/schema/collection.rb +5 -4
- data/lib/verse/schema/dictionary.rb +5 -4
- data/lib/verse/schema/field.rb +3 -3
- data/lib/verse/schema/scalar.rb +5 -4
- data/lib/verse/schema/selector.rb +5 -4
- data/lib/verse/schema/struct.rb +16 -5
- data/lib/verse/schema/version.rb +1 -1
- data/templates/README.md.erb +9 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63618ff4cf11b43ec35e8bb88adaffdf8d15ac3a49a461427fbdc3cd8908299a
|
4
|
+
data.tar.gz: 2ab22e1cd477e2b4f0e4cd070f50e2fd56e89b1c323795f4ca3cbfa1944e271d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7c5cb3e34919f47de38726ea146aa1d3d3ffe77b26d999c18da1d5e441ca06fcba4d8827c42d3b515ea7c7abd73177e7627352e1c2714ef82c0e2e196b9d01a
|
7
|
+
data.tar.gz: 4b60874afb6bcf4b7721396b9fe799b38b1b21fe4fb31c9b8fd467b835ded25ff72f8df8a2ff7bb4cddd1dca322937aa8ad1f879bcc13e7d9e012cf027cc4f63
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
## 1.1
|
2
|
+
|
3
|
+
- Add `strict` mode to `validate` which will raise an error if the input has
|
4
|
+
extra fields (in case of schema with extra_fields: false)
|
5
|
+
- Fix issue with query params by allowing coercion of String `'null'` into `nil` for `NilClass` field type
|
6
|
+
|
7
|
+
## 1.0
|
8
|
+
|
9
|
+
- First release of the Gem
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -64,6 +64,8 @@ These examples are extracted directly from the gem's specs, ensuring they are ac
|
|
64
64
|
|
65
65
|
- [Open Hash](#open-hash)
|
66
66
|
|
67
|
+
- [Strict Validation Mode](#strict-validation-mode)
|
68
|
+
|
67
69
|
|
68
70
|
- [2. Complex Structures](#2-complex-structures)
|
69
71
|
|
@@ -118,6 +120,8 @@ These examples are extracted directly from the gem's specs, ensuring they are ac
|
|
118
120
|
|
119
121
|
- [Complex Example](#complex-example)
|
120
122
|
|
123
|
+
- [Polymorphic Schema](#polymorphic-schema)
|
124
|
+
|
121
125
|
|
122
126
|
|
123
127
|
|
@@ -434,6 +438,54 @@ end
|
|
434
438
|
```
|
435
439
|
|
436
440
|
|
441
|
+
### Strict Validation Mode
|
442
|
+
|
443
|
+
|
444
|
+
```ruby
|
445
|
+
it "demonstrates strict validation for extra fields during validation" do
|
446
|
+
# By default, schemas ignore fields not defined in the schema unless `extra_fields` is used.
|
447
|
+
# You can enforce strict validation by passing `strict: true` to the `validate` method.
|
448
|
+
# This will cause validation to fail if extra fields are provided and the schema
|
449
|
+
# does not explicitly allow them via `extra_fields`.
|
450
|
+
|
451
|
+
# Please note: `strict` mode is propagated to the children schemas, when you have
|
452
|
+
# nested structures.
|
453
|
+
|
454
|
+
# Define a standard schema (extra_fields is false by default)
|
455
|
+
schema = Verse::Schema.define do
|
456
|
+
field(:name, String)
|
457
|
+
end
|
458
|
+
|
459
|
+
# Default validation (strict: false) ignores extra fields
|
460
|
+
result_default = schema.validate({ name: "John", age: 30 })
|
461
|
+
expect(result_default.success?).to be true
|
462
|
+
expect(result_default.value).to eq({ name: "John" }) # 'age' is ignored
|
463
|
+
|
464
|
+
# Strict validation (strict: true) fails with extra fields
|
465
|
+
result_strict_fail = schema.validate({ name: "John", age: 30 }, strict: true)
|
466
|
+
expect(result_strict_fail.success?).to be false
|
467
|
+
expect(result_strict_fail.errors).to eq({ age: ["is not allowed"] }) # Error on extra field 'age'
|
468
|
+
|
469
|
+
# Strict validation succeeds if no extra fields are provided
|
470
|
+
result_strict_ok = schema.validate({ name: "John" }, strict: true)
|
471
|
+
expect(result_strict_ok.success?).to be true
|
472
|
+
expect(result_strict_ok.value).to eq({ name: "John" })
|
473
|
+
|
474
|
+
# Now, define a schema that explicitly allows extra fields
|
475
|
+
schema_with_extra = Verse::Schema.define do
|
476
|
+
field(:name, String)
|
477
|
+
extra_fields # Explicitly allow extra fields
|
478
|
+
end
|
479
|
+
|
480
|
+
# Strict validation has no effect if `extra_fields` is enabled in the schema definition
|
481
|
+
result_strict_extra_ok = schema_with_extra.validate({ name: "John", age: 30 }, strict: true)
|
482
|
+
expect(result_strict_extra_ok.success?).to be true
|
483
|
+
expect(result_strict_extra_ok.value).to eq({ name: "John", age: 30 }) # Extra field 'age' is allowed and included
|
484
|
+
end
|
485
|
+
|
486
|
+
```
|
487
|
+
|
488
|
+
|
437
489
|
|
438
490
|
## 2. Complex Structures
|
439
491
|
|
@@ -1584,7 +1636,142 @@ end
|
|
1584
1636
|
```
|
1585
1637
|
|
1586
1638
|
|
1639
|
+
### Polymorphic Schema
|
1640
|
+
|
1641
|
+
|
1642
|
+
```ruby
|
1643
|
+
it "demonstrates a polymorphic schema" do
|
1644
|
+
# Polymorphism without selector model can be achieved using a builder
|
1645
|
+
# virtual object which will convert the input schema to the correct
|
1646
|
+
# schema based on the type of the input.
|
1647
|
+
#
|
1648
|
+
# Here is an example on how to do:
|
1649
|
+
#
|
1650
|
+
# 1. Define the base schema for the polymorphic structure:
|
1651
|
+
base_schema = Verse::Schema.define do
|
1652
|
+
field(:type, Symbol)
|
1653
|
+
end
|
1654
|
+
|
1655
|
+
# 2. Define the specific schemas for each type:
|
1656
|
+
facebook_schema = Verse::Schema.define(base_schema) do
|
1657
|
+
field(:url, String)
|
1658
|
+
field(:title, String)
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
google_schema = Verse::Schema.define(base_schema) do
|
1662
|
+
field(:search, String)
|
1663
|
+
field(:location, String)
|
1664
|
+
end
|
1665
|
+
|
1666
|
+
# 3. Define a builder schema. The best way to do this is to use the
|
1667
|
+
# scalar type:
|
1668
|
+
builder_schema = Verse::Schema.scalar(Hash).transform do |input, error_builder|
|
1669
|
+
|
1670
|
+
type = input[:type]
|
1671
|
+
|
1672
|
+
if type.respond_to?(:to_sym)
|
1673
|
+
type = type.to_sym
|
1674
|
+
else
|
1675
|
+
error_builder.add(:type, "invalid type")
|
1676
|
+
stop
|
1677
|
+
end
|
1678
|
+
|
1679
|
+
schema = case type
|
1680
|
+
when :facebook
|
1681
|
+
facebook_schema
|
1682
|
+
when :google
|
1683
|
+
google_schema
|
1684
|
+
else
|
1685
|
+
error_builder.add(:type, "invalid type")
|
1686
|
+
stop
|
1687
|
+
end
|
1688
|
+
|
1689
|
+
# Validate the input against the selected schema
|
1690
|
+
result = schema.validate(input, error_builder:)
|
1691
|
+
|
1692
|
+
result.value if result.success?
|
1693
|
+
end
|
1694
|
+
|
1695
|
+
# 4. Now, you can use the builder schema as placeholder for your
|
1696
|
+
# polymorphic schema:
|
1697
|
+
schema = Verse::Schema.define do
|
1698
|
+
field(:events, Array, of: builder_schema)
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
# 5. Create a complex data structure to validate
|
1702
|
+
data = {
|
1703
|
+
events: [
|
1704
|
+
{
|
1705
|
+
type: "facebook",
|
1706
|
+
url: "https://facebook.com/event/123",
|
1707
|
+
title: "Facebook Event"
|
1708
|
+
},
|
1709
|
+
{
|
1710
|
+
type: "google",
|
1711
|
+
search: "conference 2023",
|
1712
|
+
location: "New York"
|
1713
|
+
}
|
1714
|
+
]
|
1715
|
+
}
|
1716
|
+
|
1717
|
+
# 6. Validate the complex data
|
1718
|
+
result = schema.validate(data)
|
1719
|
+
# The validation succeeds
|
1720
|
+
expect(result.success?).to be true
|
1721
|
+
# The output maintains the structure with coerced values
|
1722
|
+
expect(result.value[:events][0][:type]).to eq(:facebook)
|
1723
|
+
expect(result.value[:events][0][:url]).to eq("https://facebook.com/event/123")
|
1724
|
+
expect(result.value[:events][0][:title]).to eq("Facebook Event")
|
1725
|
+
|
1726
|
+
expect(result.value[:events][1][:type]).to eq(:google)
|
1727
|
+
expect(result.value[:events][1][:search]).to eq("conference 2023")
|
1728
|
+
expect(result.value[:events][1][:location]).to eq("New York")
|
1729
|
+
|
1730
|
+
# 6.1 Invalid data
|
1731
|
+
invalid_data = {
|
1732
|
+
events: [
|
1733
|
+
{
|
1734
|
+
type: "facebook",
|
1735
|
+
# missing required url field
|
1736
|
+
title: "Facebook Event"
|
1737
|
+
},
|
1738
|
+
{
|
1739
|
+
type: "google",
|
1740
|
+
search: "conference 2023",
|
1741
|
+
# missing required location field
|
1742
|
+
},
|
1743
|
+
{
|
1744
|
+
type: "invalid",
|
1745
|
+
url: "https://invalid.com/event/123",
|
1746
|
+
title: "Invalid Event"
|
1747
|
+
}
|
1748
|
+
]
|
1749
|
+
}
|
1750
|
+
# Validate the invalid data
|
1751
|
+
invalid_result = schema.validate(invalid_data)
|
1752
|
+
# The validation fails
|
1753
|
+
expect(invalid_result.success?).to be false
|
1754
|
+
# The errors are collected
|
1755
|
+
expect(invalid_result.errors).to eq({
|
1756
|
+
:"events.0.url" => ["is required"],
|
1757
|
+
:"events.1.location" => ["is required"],
|
1758
|
+
:"events.2.type" => ["invalid type"]
|
1759
|
+
})
|
1760
|
+
end
|
1761
|
+
|
1762
|
+
```
|
1763
|
+
|
1764
|
+
|
1765
|
+
|
1766
|
+
|
1767
|
+
## License
|
1768
|
+
|
1769
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
1770
|
+
|
1771
|
+
## Sponsorship
|
1587
1772
|
|
1773
|
+
This gem was made possible thanks to the support of [Ingedata](https://ingedata.ai).
|
1774
|
+
In Ingedata, we build expert teams to support and enhance delivery of your data projects.
|
1588
1775
|
|
1589
1776
|
## Contributing
|
1590
1777
|
|
data/lib/verse/schema/base.rb
CHANGED
@@ -61,7 +61,7 @@ module Verse
|
|
61
61
|
|
62
62
|
def valid?(input) = validate(input).success?
|
63
63
|
|
64
|
-
def validate(input, error_builder: nil, locals: {}) = raise NotImplementedError
|
64
|
+
def validate(input, error_builder: nil, locals: {}, strict: false) = raise NotImplementedError
|
65
65
|
|
66
66
|
def new(arg)
|
67
67
|
result = validate(arg)
|
@@ -8,13 +8,9 @@ module Verse
|
|
8
8
|
@mapping = {}
|
9
9
|
|
10
10
|
DEFAULT_MAPPER = lambda do |type|
|
11
|
-
if type
|
12
|
-
proc do |value,
|
13
|
-
|
14
|
-
end
|
15
|
-
elsif type.is_a?(Base)
|
16
|
-
proc do |value, _opts, locals:|
|
17
|
-
type.validate(value, locals:)
|
11
|
+
if type.is_a?(Base)
|
12
|
+
proc do |value, _opts, locals:, strict:|
|
13
|
+
type.validate(value, locals:, strict:)
|
18
14
|
end
|
19
15
|
elsif type.is_a?(Class)
|
20
16
|
proc do |value|
|
@@ -36,7 +32,7 @@ module Verse
|
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
39
|
-
def transform(value, type, opts = {}, locals: {})
|
35
|
+
def transform(value, type, opts = {}, locals: {}, strict: false)
|
40
36
|
if type.is_a?(Array)
|
41
37
|
# fast-path for when the type match already
|
42
38
|
type.each do |t|
|
@@ -52,7 +48,7 @@ module Verse
|
|
52
48
|
type.each do |t|
|
53
49
|
converted = @mapping.fetch(t) do
|
54
50
|
DEFAULT_MAPPER.call(t)
|
55
|
-
end.call(value, opts, locals:)
|
51
|
+
end.call(value, opts, locals:, strict:)
|
56
52
|
|
57
53
|
if !converted.is_a?(Result) ||
|
58
54
|
(converted.is_a?(Result) && converted.success?)
|
@@ -70,7 +66,7 @@ module Verse
|
|
70
66
|
else
|
71
67
|
@mapping.fetch(type) do
|
72
68
|
DEFAULT_MAPPER.call(type)
|
73
|
-
end.call(value, opts, locals:)
|
69
|
+
end.call(value, opts, locals:, strict:)
|
74
70
|
end
|
75
71
|
end
|
76
72
|
end
|
@@ -21,7 +21,7 @@ module Verse
|
|
21
21
|
@values = values
|
22
22
|
end
|
23
23
|
|
24
|
-
def validate(input, error_builder: nil, locals: {})
|
24
|
+
def validate(input, error_builder: nil, locals: {}, strict: false)
|
25
25
|
locals = locals.dup # Ensure they are not modified
|
26
26
|
|
27
27
|
error_builder = \
|
@@ -34,7 +34,7 @@ module Verse
|
|
34
34
|
ErrorBuilder.new
|
35
35
|
end
|
36
36
|
|
37
|
-
validate_array(input, error_builder, locals)
|
37
|
+
validate_array(input, error_builder, locals, strict)
|
38
38
|
end
|
39
39
|
|
40
40
|
def dup
|
@@ -130,7 +130,7 @@ module Verse
|
|
130
130
|
|
131
131
|
protected
|
132
132
|
|
133
|
-
def validate_array(input, error_builder, locals)
|
133
|
+
def validate_array(input, error_builder, locals, strict)
|
134
134
|
locals[:__path__] ||= []
|
135
135
|
|
136
136
|
output = []
|
@@ -148,7 +148,8 @@ module Verse
|
|
148
148
|
value,
|
149
149
|
@values,
|
150
150
|
@opts,
|
151
|
-
locals
|
151
|
+
locals:,
|
152
|
+
strict:
|
152
153
|
)
|
153
154
|
|
154
155
|
if coalesced_value.is_a?(Result)
|
@@ -17,7 +17,7 @@ module Verse
|
|
17
17
|
@values = values
|
18
18
|
end
|
19
19
|
|
20
|
-
def validate(input, error_builder: nil, locals: {})
|
20
|
+
def validate(input, error_builder: nil, locals: {}, strict: false)
|
21
21
|
locals = locals.dup # Ensure they are not modified
|
22
22
|
|
23
23
|
error_builder = \
|
@@ -32,7 +32,7 @@ module Verse
|
|
32
32
|
|
33
33
|
locals[:__path__] ||= []
|
34
34
|
|
35
|
-
validate_dictionary(input, error_builder, locals)
|
35
|
+
validate_dictionary(input, error_builder, locals, strict)
|
36
36
|
end
|
37
37
|
|
38
38
|
def dup
|
@@ -117,7 +117,7 @@ module Verse
|
|
117
117
|
|
118
118
|
protected
|
119
119
|
|
120
|
-
def validate_dictionary(input, error_builder, locals)
|
120
|
+
def validate_dictionary(input, error_builder, locals, strict)
|
121
121
|
output = {}
|
122
122
|
|
123
123
|
unless input.is_a?(Hash)
|
@@ -134,7 +134,8 @@ module Verse
|
|
134
134
|
value,
|
135
135
|
@values,
|
136
136
|
@opts,
|
137
|
-
locals
|
137
|
+
locals:,
|
138
|
+
strict:
|
138
139
|
)
|
139
140
|
|
140
141
|
if coalesced_value.is_a?(Result)
|
data/lib/verse/schema/field.rb
CHANGED
@@ -347,12 +347,12 @@ module Verse
|
|
347
347
|
alias_method :<, :inherit?
|
348
348
|
|
349
349
|
# :nodoc:
|
350
|
-
def apply(value, output, error_builder, locals)
|
350
|
+
def apply(value, output, error_builder, locals, strict)
|
351
351
|
locals[:__path__].push(@name)
|
352
352
|
|
353
353
|
if @type.is_a?(Base)
|
354
354
|
error_builder.context(@name) do |error_builder|
|
355
|
-
result = @type.validate(value, error_builder:, locals:)
|
355
|
+
result = @type.validate(value, error_builder:, locals:, strict:)
|
356
356
|
|
357
357
|
# Apply field-level post-processors to the result of the nested schema validation
|
358
358
|
output[@name] = if @post_processors && error_builder.errors.empty?
|
@@ -365,7 +365,7 @@ module Verse
|
|
365
365
|
end
|
366
366
|
else
|
367
367
|
coalesced_value =
|
368
|
-
Coalescer.transform(value, @type, @opts, locals:)
|
368
|
+
Coalescer.transform(value, @type, @opts, locals:, strict:)
|
369
369
|
|
370
370
|
if coalesced_value.is_a?(Result)
|
371
371
|
error_builder.combine(@name, coalesced_value.errors)
|
data/lib/verse/schema/scalar.rb
CHANGED
@@ -21,7 +21,7 @@ module Verse
|
|
21
21
|
@values = values
|
22
22
|
end
|
23
23
|
|
24
|
-
def validate(input, error_builder: nil, locals: {})
|
24
|
+
def validate(input, error_builder: nil, locals: {}, strict: false)
|
25
25
|
locals = locals.dup # Ensure they are not modified
|
26
26
|
|
27
27
|
error_builder = \
|
@@ -34,7 +34,7 @@ module Verse
|
|
34
34
|
ErrorBuilder.new
|
35
35
|
end
|
36
36
|
|
37
|
-
validate_scalar(input, error_builder, locals)
|
37
|
+
validate_scalar(input, error_builder, locals, strict)
|
38
38
|
end
|
39
39
|
|
40
40
|
def dup
|
@@ -122,7 +122,7 @@ module Verse
|
|
122
122
|
|
123
123
|
protected
|
124
124
|
|
125
|
-
def validate_scalar(input, error_builder, locals)
|
125
|
+
def validate_scalar(input, error_builder, locals, strict)
|
126
126
|
coalesced_value = nil
|
127
127
|
|
128
128
|
begin
|
@@ -131,7 +131,8 @@ module Verse
|
|
131
131
|
input,
|
132
132
|
@values,
|
133
133
|
nil,
|
134
|
-
locals
|
134
|
+
locals:,
|
135
|
+
strict:
|
135
136
|
)
|
136
137
|
|
137
138
|
if coalesced_value.is_a?(Result)
|
@@ -20,7 +20,7 @@ module Verse
|
|
20
20
|
@values = values.transform_values{ |v| v.is_a?(Array) ? v : [v] }
|
21
21
|
end
|
22
22
|
|
23
|
-
def validate(input, error_builder: nil, locals: {})
|
23
|
+
def validate(input, error_builder: nil, locals: {}, strict: false)
|
24
24
|
locals = locals.dup # Ensure they are not modified
|
25
25
|
|
26
26
|
error_builder = \
|
@@ -35,7 +35,7 @@ module Verse
|
|
35
35
|
|
36
36
|
locals[:__path__] ||= []
|
37
37
|
|
38
|
-
validate_selector(input, error_builder, locals)
|
38
|
+
validate_selector(input, error_builder, locals, strict)
|
39
39
|
end
|
40
40
|
|
41
41
|
def dup
|
@@ -123,7 +123,7 @@ module Verse
|
|
123
123
|
|
124
124
|
protected
|
125
125
|
|
126
|
-
def validate_selector(input, error_builder, locals)
|
126
|
+
def validate_selector(input, error_builder, locals, strict)
|
127
127
|
output = {}
|
128
128
|
|
129
129
|
selector = locals.fetch(:selector) do
|
@@ -154,7 +154,8 @@ module Verse
|
|
154
154
|
input,
|
155
155
|
fetched_values,
|
156
156
|
nil,
|
157
|
-
locals
|
157
|
+
locals:,
|
158
|
+
strict:
|
158
159
|
)
|
159
160
|
|
160
161
|
if coalesced_value.is_a?(Result)
|
data/lib/verse/schema/struct.rb
CHANGED
@@ -69,7 +69,7 @@ module Verse
|
|
69
69
|
|
70
70
|
def valid?(input) = validate(input).success?
|
71
71
|
|
72
|
-
def validate(input, error_builder: nil, locals: {})
|
72
|
+
def validate(input, error_builder: nil, locals: {}, strict: false)
|
73
73
|
error_builder = \
|
74
74
|
case error_builder
|
75
75
|
when String
|
@@ -87,7 +87,7 @@ module Verse
|
|
87
87
|
|
88
88
|
locals = locals.dup # Ensure they are not modified
|
89
89
|
|
90
|
-
validate_hash(input, error_builder, locals)
|
90
|
+
validate_hash(input, error_builder, locals, strict)
|
91
91
|
end
|
92
92
|
|
93
93
|
def dup
|
@@ -276,7 +276,7 @@ module Verse
|
|
276
276
|
|
277
277
|
protected
|
278
278
|
|
279
|
-
def validate_hash(input, error_builder, locals)
|
279
|
+
def validate_hash(input, error_builder, locals, strict)
|
280
280
|
locals[:__path__] ||= []
|
281
281
|
|
282
282
|
input = input.transform_keys(&:to_sym)
|
@@ -295,14 +295,25 @@ module Verse
|
|
295
295
|
end
|
296
296
|
|
297
297
|
if exists
|
298
|
-
field.apply(value, output, error_builder, locals)
|
298
|
+
field.apply(value, output, error_builder, locals, strict)
|
299
299
|
elsif field.default?
|
300
|
-
field.apply(field.default, output, error_builder, locals)
|
300
|
+
field.apply(field.default, output, error_builder, locals, strict)
|
301
301
|
elsif field.required?
|
302
302
|
error_builder.add(field.key, "is required")
|
303
303
|
end
|
304
304
|
end
|
305
305
|
|
306
|
+
# If strict mode is enabled, check for extra fields
|
307
|
+
# that are not defined in the schema.
|
308
|
+
if !@extra_fields && strict
|
309
|
+
extra_keys = input.keys - @cache_field_name
|
310
|
+
if extra_keys.any?
|
311
|
+
extra_keys.each do |key|
|
312
|
+
error_builder.add(key, "is not allowed")
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
306
317
|
if @post_processors && error_builder.errors.empty?
|
307
318
|
output = @post_processors.call(output, nil, error_builder, **locals)
|
308
319
|
end
|
data/lib/verse/schema/version.rb
CHANGED
data/templates/README.md.erb
CHANGED
@@ -68,6 +68,15 @@ These examples are extracted directly from the gem's specs, ensuring they are ac
|
|
68
68
|
<% end %>
|
69
69
|
<% end %>
|
70
70
|
|
71
|
+
## License
|
72
|
+
|
73
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
74
|
+
|
75
|
+
## Sponsorship
|
76
|
+
|
77
|
+
This gem was made possible thanks to the support of [Ingedata](https://ingedata.ai).
|
78
|
+
In Ingedata, we build expert teams to support and enhance delivery of your data projects.
|
79
|
+
|
71
80
|
## Contributing
|
72
81
|
|
73
82
|
Bug reports and pull requests are welcome on GitHub at https://github.com/verse-rb/verse-schema.
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: verse-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yacine Petitprez
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-23 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: attr_chainable
|
@@ -33,6 +33,7 @@ files:
|
|
33
33
|
- ".rspec"
|
34
34
|
- ".rubocop-https---relaxed-ruby-style-rubocop-yml"
|
35
35
|
- ".rubocop.yml"
|
36
|
+
- CHANGELOG.md
|
36
37
|
- Gemfile
|
37
38
|
- Gemfile.lock
|
38
39
|
- README.md
|