easy_talk 0.2.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3b84eeed5e8d6430c3bbaf97936ec90a29554dcbd71905553ecaf2f66b82877
4
- data.tar.gz: 74fa329ca8574c8d8d8ec2b3daf6dee3a8d46a3550c53fb30ceb1709487243d9
3
+ metadata.gz: fa39fe0359df9334a186807b3e67679b752806db59eb9b03829ec875c6382818
4
+ data.tar.gz: 150814754a0604fc0149bf042c73d798fe042935ffde11b52c2254ac765c05e8
5
5
  SHA512:
6
- metadata.gz: 59be99a0311ec3c5d941e63cc2299e26d2a84c1a53ff88f6bd561dbd1b046dc3f4e5d68c8037724cd295df8d542a7a24621374cc535422920200a11ae66507e5
7
- data.tar.gz: 2eabc32e703f00a68d47d1152fc1a42cc963e0f5ba05aea76b57b7ccccde670dcb4361811b8af812b85d2c78880f7b375e536d7ce7f0f12a7177dd8b80046775
6
+ metadata.gz: ea9d64a999260983afac690850ae5095b4e2d00583feb1a6dd4baa0a0cb377a82566dae1245e1b767e5ff79549f28e60209b43fa3d765a8b51c46ee6969425bd
7
+ data.tar.gz: 20e3bea29ad389126937924f431f8729be43b172f8f868ae5fc0189d729e1d19642a9fa0e74a34322e1acafd2b74c6b2fad20bb8f081c7ea504364a2daaf3d99
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [1.0.0] - 2024-06-01
2
+ - Use `Hash` instead of `:object` for inline object schema definition.
3
+ example:
4
+ ```ruby
5
+ property :email, Hash do
6
+ property :address, :string
7
+ property :verified, :boolean
8
+ end
9
+ ```
10
+ - Loosen up the gemspec version requirement. Makes it flexible to use the library with future versions of Rails (i.e 8.*).
11
+ - Removed JSONScheemer gem dependency.
12
+ - The library does not validate by default anymore. Validating an instance requires that you explicitly define ActiveModel validations in your EasyTalk model. See: https://github.com/sergiobayona/easy_talk/blob/main/spec/easy_talk/activemodel_integration_spec.rb.
13
+ - Internal improvements to `EasyTalk::ObjectBuilder` class. No changes to the public API.
14
+ - Expanded the test suite.
15
+
16
+ ## [0.2.2] - 2024-05-17
17
+ - Fixed a bug where optional properties were not excluded from the required list.
18
+
1
19
  ## [0.2.1] - 2024-05-06
2
20
  - Run JSON Schema validations using ActiveModel's validations.
3
21
 
data/README.md CHANGED
@@ -4,10 +4,9 @@ EasyTalk is a Ruby library that simplifies defining and generating JSON Schema d
4
4
 
5
5
  Key Features
6
6
  * Intuitive Schema Definition: Use Ruby classes and methods to define JSON Schema documents easily.
7
- * JSON Schema Compliance: Implements the JSON Schema specification to ensure compatibility and standards adherence.
8
- * LLM Function Support: Ideal for integrating with Large Language Models (LLMs) such as OpenAI's GPT-3.5-turbo and GPT-4. EasyTalk enables you to effortlessly create JSON Schema documents needed to describe the inputs and outputs of LLM function calls.
9
- * Validation: Validates JSON inputs and outputs against defined schemas to ensure they meet expected formats and types. Write custom validations using ActiveModel's validations.
10
- * Integration with ActiveModel: EasyTalk integrates with ActiveModel to provide additional functionality such as attribute assignment, introspections, validations, translation (i18n), and more.
7
+ * LLM Function Support: Ideal for integrating with Large Language Models (LLMs) such as OpenAI’s GPT series. EasyTalk enables you to effortlessly create JSON Schema documents describing the inputs and outputs of LLM function calls.
8
+ * Schema Composition: Define EasyTalk models and reference them in other EasyTalk models to create complex schemas.
9
+ * Validation: Write validations using ActiveModels validations.
11
10
 
12
11
  Inspiration
13
12
  Inspired by Python's Pydantic library, EasyTalk brings similar functionality to the Ruby ecosystem, providing a Ruby-friendly approach to JSON Schema operations.
@@ -18,85 +17,78 @@ Example Use:
18
17
  class User
19
18
  include EasyTalk::Model
20
19
 
20
+ validates :name, :email, :group, presence: true
21
+ validates :age, numericality: { greater_than_or_equal_to: 18, less_than_or_equal_to: 100 }
22
+
21
23
  define_schema do
22
24
  title "User"
23
25
  description "A user of the system"
24
26
  property :name, String, description: "The user's name", title: "Full Name"
25
- property :email, :object do
27
+ property :email, Hash do
26
28
  property :address, String, format: "email", description: "The user's email", title: "Email Address"
27
29
  property :verified, T::Boolean, description: "Whether the email is verified"
28
30
  end
29
- property :group, String, enum: [1, 2, 3], default: 1, description: "The user's group"
31
+ property :group, Integer, enum: [1, 2, 3], default: 1, description: "The user's group"
30
32
  property :age, Integer, minimum: 18, maximum: 100, description: "The user's age"
31
- property :tags, T::Array[String], min_items: 1, unique_item: true, description: "The user's tags"
33
+ property :tags, T::Array[String], min_items: 1, unique_items: true, description: "The user's tags"
32
34
  end
33
35
  end
34
36
  ```
35
37
 
36
- Calling `User.json_schema` will return the JSON Schema for the User class:
38
+ Calling `User.json_schema` will return the Ruby representation of the JSON Schema for the `User` class:
37
39
 
38
- ```json
40
+ ```ruby
39
41
  {
40
- "title": "User",
41
- "description": "A user of the system",
42
- "type": "object",
43
- "properties": {
44
- "name": {
45
- "title": "Full Name",
46
- "description": "The user's name",
47
- "type": "string"
48
- },
49
- "email": {
50
- "type": "object",
51
- "properties": {
52
- "address": {
53
- "title": "Email Address",
54
- "description": "The user's email",
55
- "type": "string",
56
- "format": "email"
57
- },
58
- "verified": {
59
- "type": "boolean",
60
- "description": "Whether the email is verified"
61
- }
62
- },
63
- "required": [
64
- "address",
65
- "verified"
66
- ]
67
- },
68
- "group": {
69
- "type": "number",
70
- "enum": [1, 2, 3],
71
- "default": 1,
72
- "description": "The user's group"
73
- },
74
- "age": {
75
- "type": "integer",
76
- "minimum": 18,
77
- "maximum": 100,
78
- "description": "The user's age"
42
+ "type" => "object",
43
+ "title" => "User",
44
+ "description" => "A user of the system",
45
+ "properties" => {
46
+ "name" => {
47
+ "type" => "string", "title" => "Full Name", "description" => "The user's name"
48
+ },
49
+ "email" => {
50
+ "type" => "object",
51
+ "properties" => {
52
+ "address" => {
53
+ "type" => "string", "title" => "Email Address", "description" => "The user's email", "format" => "email"
79
54
  },
80
- "tags": {
81
- "type": "array",
82
- "items": {
83
- "type": "string"
84
- },
85
- "minItems": 1,
86
- "uniqueItems": true,
87
- "description": "The user's tags"
55
+ "verified" => {
56
+ "type" => "boolean", "description" => "Whether the email is verified"
88
57
  }
58
+ },
59
+ "required" => ["address", "verified"]
60
+ },
61
+ "group" => {
62
+ "type" => "integer", "description" => "The user's group", "enum" => [1, 2, 3], "default" => 1
63
+ },
64
+ "age" => {
65
+ "type" => "integer", "description" => "The user's age", "minimum" => 18, "maximum" => 100
89
66
  },
90
- "required:": [
91
- "name",
92
- "email",
93
- "group",
94
- "age",
95
- "tags"
96
- ]
67
+ "tags" => {
68
+ "type" => "array",
69
+ "items" => { "type" => "string" },
70
+ "description" => "The user's tags",
71
+ "minItems" => 1,
72
+ "uniqueItems" => true
73
+ }
74
+ },
75
+ "required" => ["name", "email", "group", "age", "tags"]
97
76
  }
98
77
  ```
99
78
 
79
+ Instantiate a User object and validate it with ActiveModel validations:
80
+
81
+ ```ruby
82
+ user = User.new(name: "John Doe", email: { address: "john@test.com", verified: true }, group: 1, age: 25, tags: ["tag1", "tag2"])
83
+ user.valid? # => true
84
+
85
+ user.name = nil
86
+ user.valid? # => false
87
+
88
+ user.errors.full_messages # => ["Name can't be blank"]
89
+ user.errors["name"] # => ["can't be blank"]
90
+ ```
91
+
100
92
  ## Installation
101
93
 
102
94
  install the gem by running the following command in your terminal:
@@ -105,12 +97,20 @@ Calling `User.json_schema` will return the JSON Schema for the User class:
105
97
 
106
98
  ## Usage
107
99
 
108
- Simply include the `EasyTalk::Model` module in your Ruby class, define the schema using the `define_schema` block and call the `json_schema` class method to generate the JSON Schema document.
100
+ Simply include the `EasyTalk::Model` module in your Ruby class, define the schema using the `define_schema` block, and call the `json_schema` class method to generate the JSON Schema document.
109
101
 
110
102
 
111
103
  ## Schema Definition
112
104
 
113
- In the example above, the `define_schema` method is used to add a description and a title to the schema document. The `property` method is used to define the properties of the schema document. The `property` method accepts the name of the property as a symbol, the type, which can be a generic Ruby type or a [Sorbet type](https://sorbet.org/docs/stdlib-generics), and a hash of constraints as options.
105
+ In the example above, the define_schema method adds a title and description to the schema. The property method defines properties of the schema document. property accepts:
106
+
107
+ * A name (symbol)
108
+ * A type (generic Ruby type like String/Integer, a Sorbet type like T::Boolean, or one of the custom types like T::AnyOf[...])
109
+ * A hash of constraints (e.g., minimum: 18, enum: [1, 2, 3], etc.)
110
+
111
+ ## Why Sortbet-style types?
112
+
113
+ Ruby doesn’t natively allow complex types like Array[String] or Array[Integer]. Sorbet-style types let you define these compound types clearly. EasyTalk uses this style to handle property types such as T::Array[String] or T::AnyOf[ClassA, ClassB].
114
114
 
115
115
  ## Property Constraints
116
116
 
@@ -119,88 +119,89 @@ Property constraints are type-dependent. Refer to the [CONSTRAINTS.md](CONSTRAIN
119
119
 
120
120
  ## Schema Composition
121
121
 
122
- EasyTalk supports schema composition. You can define a schema for a nested object by defining a new class and including the `EasyTalk::Model` module. You can then reference the nested schema in the parent schema using the following special types:
122
+ EasyTalk supports schema composition. You can define a schema for a nested object by defining a new class that includes `EasyTalk::Model`. You can then reference the nested schema in the parent using special types:
123
+
124
+ T::OneOf[Model1, Model2, ...] — The property must match at least one of the specified schemas
125
+ T::AnyOf[Model1, Model2, ...] — The property can match any of the specified schemas
126
+ T::AllOf[Model1, Model2, ...] — The property must match all of the specified schemas
123
127
 
124
- - T::OneOf[Model1, Model2, ...] - The property must match at least one of the specified schemas.
125
- - T::AnyOf[Model1, Model2, ...] - The property can match any of the specified schemas.
126
- - T::AllOf[Model1, Model2, ...] - The property must match all of the specified schemas.
128
+ Example: A Payment object that can be a credit card, PayPal, or bank transfer:
127
129
 
128
- Here is an example where we define a schema for a payment object that can be a credit card, a PayPal account, or a bank transfer. The first three classes represent the schemas for the different payment methods. The `Payment` class represents the schema for the payment object where the `Details` property can be any of the payment method schemas.
129
130
 
130
131
  ```ruby
131
- class CreditCard
132
- include EasyTalk::Model
133
-
134
- define_schema do
135
- property :CardNumber, String
136
- property :CardType, String, enum: %w[Visa MasterCard AmericanExpress]
137
- property :CardExpMonth, Integer, minimum: 1, maximum: 12
138
- property :CardExpYear, Integer, minimum: Date.today.year, maximum: Date.today.year + 10
139
- property :CardCVV, String, pattern: '^[0-9]{3,4}$'
140
- additional_properties false
141
- end
132
+ class CreditCard
133
+ include EasyTalk::Model
134
+
135
+ define_schema do
136
+ property :CardNumber, String
137
+ property :CardType, String, enum: %w[Visa MasterCard AmericanExpress]
138
+ property :CardExpMonth, Integer, minimum: 1, maximum: 12
139
+ property :CardExpYear, Integer, minimum: Date.today.year, maximum: Date.today.year + 10
140
+ property :CardCVV, String, pattern: '^[0-9]{3,4}$'
141
+ additional_properties false
142
142
  end
143
+ end
143
144
 
144
- class Paypal
145
- include EasyTalk::Model
145
+ class Paypal
146
+ include EasyTalk::Model
146
147
 
147
- define_schema do
148
- property :PaypalEmail, String, format: 'email'
149
- property :PaypalPasswordEncrypted, String
150
- additional_properties false
151
- end
148
+ define_schema do
149
+ property :PaypalEmail, String, format: 'email'
150
+ property :PaypalPasswordEncrypted, String
151
+ additional_properties false
152
152
  end
153
+ end
153
154
 
154
- class BankTransfer
155
- include EasyTalk::Model
155
+ class BankTransfer
156
+ include EasyTalk::Model
156
157
 
157
- define_schema do
158
- property :BankName, String
159
- property :AccountNumber, String
160
- property :RoutingNumber, String
161
- property :AccountType, String, enum: %w[Checking Savings]
162
- additional_properties false
163
- end
158
+ define_schema do
159
+ property :BankName, String
160
+ property :AccountNumber, String
161
+ property :RoutingNumber, String
162
+ property :AccountType, String, enum: %w[Checking Savings]
163
+ additional_properties false
164
164
  end
165
+ end
165
166
 
166
- class Payment
167
- include EasyTalk::Model
167
+ class Payment
168
+ include EasyTalk::Model
168
169
 
169
- define_schema do
170
- title 'Payment'
171
- description 'Payment info'
172
- property :PaymentMethod, String, enum: %w[CreditCard Paypal BankTransfer]
173
- property :Details, T::AnyOf[CreditCard, Paypal, BankTransfer]
174
- end
170
+ define_schema do
171
+ title 'Payment'
172
+ description 'Payment info'
173
+ property :PaymentMethod, String, enum: %w[CreditCard Paypal BankTransfer]
174
+ property :Details, T::AnyOf[CreditCard, Paypal, BankTransfer]
175
175
  end
176
-
176
+ end
177
177
  ```
178
178
 
179
179
  ## Type Checking and Schema Constraints
180
180
 
181
- EasyTalk uses [Sorbet](https://sorbet.org/) to perform type checking on the property constraint values. The `property` method accepts a type as the second argument. The type can be a Ruby class or a Sorbet type. For example, `String`, `Integer`, `T::Array[String]`, etc.
182
-
183
- EasyTalk raises an error if the constraint values do not match the property type. For example, if you specify the `enum` constraint with the values [1,2,3], but the property type is `String`, EasyTalk will raise a type error.
181
+ EasyTalk uses a combination of standard Ruby types (`String`, `Integer`), Sorbet types (`T::Boolean`, `T::Array[String]`, etc.), and custom Sorbet-style types (`T::AnyOf[]`, `T::OneOf[]`) to perform basic type checking. For example:
184
182
 
185
- EasyTalk also raises an error if the constraints are not valid for the property type. For example, if you define a property with a `minimum` or a `maximum` constraint, but the type is `String`, EasyTalk will raise an error.
183
+ If you specify `enum: [1,2,3]` but the property type is `String`, EasyTalk raises a type error.
184
+ If you define `minimum: 1` on a `String` property, it raises an error because minimum applies only to numeric types.
186
185
 
187
186
  ## Schema Validation
188
187
 
189
- EasyTalk does not yet perform JSON validation. So far, it only aims to generate a valid JSON Schema document. You can use the `json_schema` method to generate the JSON Schema and use a JSON Schema validator library like [JSONSchemer](https://github.com/davishmcclurg/json_schemer) to validate JSON against. See https://json-schema.org/implementations#validators-ruby for a list of JSON Schema validator libraries for Ruby.
190
-
191
- The goal is to introduce JSON validation in the near future.
188
+ You can instantiate an EasyTalk model with a hash of attributes and validate it using standard ActiveModel validations. EasyTalk does not automatically validate instances; you must explicitly define ActiveModel validations in your EasyTalk model. See [spec/easy_talk/activemodel_integration_spec.rb](ActiveModel Integration Spec) for examples.
192
189
 
193
190
  ## JSON Schema Specifications
194
191
 
195
- EasyTalk is currently very loose about JSON Schema specifications. It does not enforce the use of the latest JSON Schema specifications. Support for the dictionary of JSON Schema keywords varies depending on the keyword. The goal is to have robust support for the latest JSON Schema specifications in the near future.
192
+ EasyTalk is currently loose about JSON Schema versions. It doesn’t strictly enforce or adhere to any particular version of the specification. The goal is to add more robust support for the latest JSON Schema specs in the future.
196
193
 
197
- To learn about the current EasyTalk capabilities, take a look at the [spec/easy_talk/examples](https://github.com/sergiobayona/easy_talk/tree/main/spec/easy_talk/examples) folder. The examples are used to test the JSON Schema generation.
194
+ To learn about current capabilities, see the [spec/easy_talk/examples](https://github.com/sergiobayona/easy_talk/tree/main/spec/easy_talk/examples) folder. The examples illustrate how EasyTalk generates JSON Schema in different scenarios.
198
195
 
199
196
  ## Development
200
197
 
201
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
198
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that lets you experiment.
202
199
 
203
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
200
+ To install this gem onto your local machine, run:
201
+
202
+ ```bash
203
+ bundle exec rake install
204
+ ```
204
205
 
205
206
  ## Contributing
206
207
 
data/docs/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ _site
2
+ .sass-cache
3
+ .jekyll-cache
4
+ .jekyll-metadata
5
+ vendor
data/docs/404.html ADDED
@@ -0,0 +1,25 @@
1
+ ---
2
+ permalink: /404.html
3
+ layout: default
4
+ ---
5
+
6
+ <style type="text/css" media="screen">
7
+ .container {
8
+ margin: 10px auto;
9
+ max-width: 600px;
10
+ text-align: center;
11
+ }
12
+ h1 {
13
+ margin: 30px 0;
14
+ font-size: 4em;
15
+ line-height: 1;
16
+ letter-spacing: -1px;
17
+ }
18
+ </style>
19
+
20
+ <div class="container">
21
+ <h1>404</h1>
22
+
23
+ <p><strong>Page not found :(</strong></p>
24
+ <p>The requested page could not be found.</p>
25
+ </div>
data/docs/Gemfile ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ # Hello! This is where you manage which Jekyll version is used to run.
5
+ # When you want to use a different version, change it below, save the
6
+ # file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
7
+ #
8
+ # bundle exec jekyll serve
9
+ #
10
+ # This will help ensure the proper Jekyll version is running.
11
+ # Happy Jekylling!
12
+ # gem "jekyll", "~> 4.3.3"
13
+ gem 'github-pages', group: :jekyll_plugins
14
+
15
+ gem 'webrick'
16
+ # This is the default theme for new Jekyll sites. You may change this to anything you like.
17
+ gem 'minima', '~> 2.5'
18
+ # If you want to use GitHub Pages, remove the "gem "jekyll"" above and
19
+ # uncomment the line below. To upgrade, run `bundle update github-pages`.
20
+ # gem "github-pages", group: :jekyll_plugins
21
+ # If you have any plugins, put them here!
22
+ group :jekyll_plugins do
23
+ gem 'jekyll-feed', '~> 0.12'
24
+ end
25
+
26
+ # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
27
+ # and associated library.
28
+ platforms :mingw, :x64_mingw, :mswin, :jruby do
29
+ gem 'tzinfo', '>= 1', '< 3'
30
+ gem 'tzinfo-data'
31
+ end
32
+
33
+ # Performance-booster for watching directories on Windows
34
+ gem 'wdm', '~> 0.1.1', platforms: %i[mingw x64_mingw mswin]
35
+
36
+ # Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
37
+ # do not have a Java counterpart.
38
+ gem 'http_parser.rb', '~> 0.6.0', platforms: [:jruby]
data/docs/_config.yml ADDED
@@ -0,0 +1,53 @@
1
+ # Welcome to Jekyll!
2
+ #
3
+ # This config file is meant for settings that affect your whole blog, values
4
+ # which you are expected to set up once and rarely edit after that. If you find
5
+ # yourself editing this file very often, consider using Jekyll's data files
6
+ # feature for the data you need to update frequently.
7
+ #
8
+ # For technical reasons, this file is *NOT* reloaded automatically when you use
9
+ # 'bundle exec jekyll serve'. If you change this file, please restart the server process.
10
+ #
11
+ # If you need help with YAML syntax, here are some quick references for you:
12
+ # https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
13
+ # https://learnxinyminutes.com/docs/yaml/
14
+ #
15
+ # Site settings
16
+ # These are used to personalize your new site. If you look in the HTML files,
17
+ # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
18
+ # You can create any custom variable you would like, and they will be accessible
19
+ # in the templates via {{ site.myvariable }}.
20
+
21
+ title: EasyTalk
22
+ email: bayona.sergio@gmail.com
23
+ description: >- # this means to ignore newlines until "baseurl:"
24
+ EasyTalk: define and generate JSON Schema documents.
25
+ baseurl: "/easy_talk" # the subpath of your site, e.g. /blog
26
+ url: "https://sergiobayona.github.io" # the base hostname & protocol for your site, e.g. http://example.com
27
+ twitter_username: sergiobayona
28
+ github_username: sergiobayona
29
+
30
+ # Build settings
31
+ theme: minima
32
+ plugins:
33
+ - jekyll-feed
34
+
35
+ # Exclude from processing.
36
+ # The following items will not be processed, by default.
37
+ # Any item listed under the `exclude:` key here will be automatically added to
38
+ # the internal "default list".
39
+ #
40
+ # Excluded items can be processed by explicitly listing the directories or
41
+ # their entries' file path in the `include:` list.
42
+ #
43
+ # exclude:
44
+ # - .sass-cache/
45
+ # - .jekyll-cache/
46
+ # - gemfiles/
47
+ # - Gemfile
48
+ # - Gemfile.lock
49
+ # - node_modules/
50
+ # - vendor/bundle/
51
+ # - vendor/cache/
52
+ # - vendor/gems/
53
+ # - vendor/ruby/
@@ -0,0 +1,29 @@
1
+ ---
2
+ layout: post
3
+ title: "Welcome to Jekyll!"
4
+ date: 2024-05-07 18:39:19 -0500
5
+ categories: jekyll update
6
+ ---
7
+ You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated.
8
+
9
+ Jekyll requires blog post files to be named according to the following format:
10
+
11
+ `YEAR-MONTH-DAY-title.MARKUP`
12
+
13
+ Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.
14
+
15
+ Jekyll also offers powerful support for code snippets:
16
+
17
+ {% highlight ruby %}
18
+ def print_hi(name)
19
+ puts "Hi, #{name}"
20
+ end
21
+ print_hi('Tom')
22
+ #=> prints 'Hi, Tom' to STDOUT.
23
+ {% endhighlight %}
24
+
25
+ Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk].
26
+
27
+ [jekyll-docs]: https://jekyllrb.com/docs/home
28
+ [jekyll-gh]: https://github.com/jekyll/jekyll
29
+ [jekyll-talk]: https://talk.jekyllrb.com/
@@ -0,0 +1,18 @@
1
+ ---
2
+ layout: page
3
+ title: About
4
+ permalink: /about/
5
+ ---
6
+
7
+ This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/)
8
+
9
+ You can find the source code for Minima at GitHub:
10
+ [jekyll][jekyll-organization] /
11
+ [minima](https://github.com/jekyll/minima)
12
+
13
+ You can find the source code for Jekyll at GitHub:
14
+ [jekyll][jekyll-organization] /
15
+ [jekyll](https://github.com/jekyll/jekyll)
16
+
17
+
18
+ [jekyll-organization]: https://github.com/jekyll
@@ -0,0 +1,7 @@
1
+ ---
2
+ # Feel free to add content and custom Front Matter to this file.
3
+ # To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
4
+
5
+ layout: home
6
+ ---
7
+ EasyTalk is a Ruby library that simplifies defining and generating JSON Schema documents, and validates that JSON data conforms to these schemas.
@@ -1,15 +1,21 @@
1
- # frozen_string_literal: true
2
-
3
1
  require_relative 'base_builder'
2
+ require 'set'
4
3
 
5
4
  module EasyTalk
6
5
  module Builders
7
- # Builder class for json schema objects.
6
+ #
7
+ # ObjectBuilder is responsible for turning a SchemaDefinition of an "object" type
8
+ # into a validated JSON Schema hash. It:
9
+ #
10
+ # 1) Recursively processes the schema’s :properties,
11
+ # 2) Determines which properties are required (unless nilable or optional),
12
+ # 3) Handles sub-schema composition (allOf, anyOf, oneOf, not),
13
+ # 4) Produces the final object-level schema hash.
14
+ #
8
15
  class ObjectBuilder < BaseBuilder
9
16
  extend T::Sig
10
17
 
11
- attr_reader :schema
12
-
18
+ # Required by BaseBuilder: recognized schema options for "object" types
13
19
  VALID_OPTIONS = {
14
20
  properties: { type: T::Hash[T.any(Symbol, String), T.untyped], key: :properties },
15
21
  additional_properties: { type: T::Boolean, key: :additionalProperties },
@@ -24,70 +30,173 @@ module EasyTalk
24
30
 
25
31
  sig { params(schema_definition: EasyTalk::SchemaDefinition).void }
26
32
  def initialize(schema_definition)
33
+ # Keep a reference to the original schema definition
27
34
  @schema_definition = schema_definition
28
- @schema = schema_definition.schema.dup
29
- @required_properties = []
30
- name = schema_definition.name ? schema_definition.name.to_sym : :klass
31
- super(name, { type: 'object' }, options, VALID_OPTIONS)
35
+ # Duplicate the raw schema hash so we can mutate it safely
36
+ @original_schema = schema_definition.schema.dup
37
+
38
+ # We'll collect required property names in this Set
39
+ @required_properties = Set.new
40
+
41
+ # Usually the name is a string (class name). Fallback to :klass if nil.
42
+ name_for_builder = schema_definition.name ? schema_definition.name.to_sym : :klass
43
+
44
+ # Build the base structure: { type: 'object' } plus any top-level options
45
+ super(
46
+ name_for_builder,
47
+ { type: 'object' }, # minimal "object" structure
48
+ build_options_hash, # method below merges & cleans final top-level keys
49
+ VALID_OPTIONS
50
+ )
32
51
  end
33
52
 
34
53
  private
35
54
 
36
- def properties_from_schema_definition
37
- properties = schema.delete(:properties) || {}
38
- properties.each_with_object({}) do |(property_name, options), context|
39
- add_required_property(property_name, options)
40
- context[property_name] = build_property(property_name, options)
55
+ ##
56
+ # Main aggregator: merges the top-level schema keys (like :properties, :subschemas)
57
+ # into a single hash that we’ll feed to BaseBuilder.
58
+ def build_options_hash
59
+ # Start with a copy of the raw schema
60
+ merged = @original_schema.dup
61
+
62
+ # Extract and build sub-schemas first (handles allOf/anyOf/oneOf references, etc.)
63
+ process_subschemas(merged)
64
+
65
+ # Build :properties into a final form (and find "required" props)
66
+ merged[:properties] = build_properties(merged.delete(:properties))
67
+
68
+ # Populate the final "required" array from @required_properties
69
+ merged[:required] = @required_properties.to_a if @required_properties.any?
70
+
71
+ # Prune empty or nil values so we don't produce stuff like "properties": {} unnecessarily
72
+ merged.reject! { |_k, v| v.nil? || v == {} || v == [] }
73
+
74
+ merged
75
+ end
76
+
77
+ ##
78
+ # Given the property definitions hash, produce a new hash of
79
+ # { property_name => [Property or nested schema builder result] }.
80
+ #
81
+ def build_properties(properties_hash)
82
+ return {} unless properties_hash.is_a?(Hash)
83
+
84
+ # Cache with a key based on property name and its full configuration
85
+ @properties_cache ||= {}
86
+
87
+ properties_hash.each_with_object({}) do |(prop_name, prop_options), result|
88
+ cache_key = [prop_name, prop_options].hash
89
+
90
+ # Use cache if the exact property and configuration have been processed before
91
+ @properties_cache[cache_key] ||= begin
92
+ mark_required_unless_optional(prop_name, prop_options)
93
+ build_property(prop_name, prop_options)
94
+ end
95
+
96
+ result[prop_name] = @properties_cache[cache_key]
41
97
  end
42
98
  end
43
99
 
44
- # rubocop:disable Style/DoubleNegation
45
- def add_required_property(property_name, options)
46
- return if options.is_a?(Hash) && !!(options[:type].respond_to?(:nilable?) && options[:type].nilable?)
100
+ ##
101
+ # Decide if a property should be required. If it's optional or nilable,
102
+ # we won't include it in the "required" array.
103
+ #
104
+ def mark_required_unless_optional(prop_name, prop_options)
105
+ return if property_optional?(prop_options)
106
+
107
+ @required_properties.add(prop_name)
108
+ end
109
+
110
+ ##
111
+ # Returns true if the property is declared optional or is T.nilable(...).
112
+ #
113
+ def property_optional?(prop_options)
114
+ # For convenience, treat :type as an object
115
+ type_obj = prop_options[:type]
47
116
 
48
- return if options.respond_to?(:optional?) && options.optional?
117
+ # Check Sorbet's nilable (like T.nilable(String))
118
+ return true if type_obj.respond_to?(:nilable?) && type_obj.nilable?
49
119
 
50
- @required_properties << property_name
120
+ # Check constraints[:optional]
121
+ return true if prop_options.dig(:constraints, :optional)
122
+
123
+ false
51
124
  end
52
- # rubocop:enable Style/DoubleNegation
53
125
 
54
- def build_property(property_name, options)
55
- if options.is_a?(EasyTalk::SchemaDefinition)
56
- ObjectBuilder.new(options).build
57
- else
58
- Property.new(property_name, options[:type], options[:constraints])
59
- end
126
+ ##
127
+ # Builds a single property. Could be a nested schema if it has sub-properties,
128
+ # or a standard scalar property (String, Integer, etc.).
129
+ #
130
+ def build_property(prop_name, prop_options)
131
+ @property_cache ||= {}
132
+
133
+ # Memoize so we only build each property once
134
+ @property_cache[prop_name] ||= if prop_options[:properties]
135
+ # This indicates block-style definition => nested schema
136
+ nested_schema_builder(prop_options)
137
+ else
138
+ # Normal property: e.g. { type: String, constraints: {...} }
139
+ handle_nilable_type(prop_options)
140
+ Property.new(prop_name, prop_options[:type], prop_options[:constraints])
141
+ end
60
142
  end
61
143
 
62
- def subschemas_from_schema_definition
63
- subschemas = schema.delete(:subschemas) || []
64
- subschemas.each do |subschema|
65
- add_definitions(subschema)
66
- add_references(subschema)
67
- end
144
+ ##
145
+ # Build a child schema by calling another ObjectBuilder on the nested SchemaDefinition.
146
+ #
147
+ def nested_schema_builder(prop_options)
148
+ child_schema_def = prop_options[:properties]
149
+ # If user used T.nilable(...) with a block, unwrap the nilable
150
+ handle_nilable_type(prop_options)
151
+ ObjectBuilder.new(child_schema_def).build
68
152
  end
69
153
 
70
- def add_definitions(subschema)
71
- definitions = subschema.items.each_with_object({}) do |item, hash|
72
- hash[item.name] = item.schema
154
+ ##
155
+ # If the type is T.nilable(SomeType), unwrap it so we produce the correct schema.
156
+ # This logic is borrowed from the old #handle_option_type method.
157
+ #
158
+ def handle_nilable_type(prop_options)
159
+ type_obj = prop_options[:type]
160
+ return unless type_obj.respond_to?(:nilable?) && type_obj.nilable?
161
+
162
+ # If the underlying raw_type isn't T::Types::TypedArray, then we unwrap it
163
+ return unless type_obj.unwrap_nilable.class != T::Types::TypedArray
164
+
165
+ prop_options[:type] = type_obj.unwrap_nilable.raw_type
166
+ end
167
+
168
+ ##
169
+ # Process top-level composition keywords (e.g. allOf, anyOf, oneOf),
170
+ # converting them to definitions + references if appropriate.
171
+ #
172
+ def process_subschemas(schema_hash)
173
+ subschemas = schema_hash.delete(:subschemas) || []
174
+ subschemas.each do |subschema|
175
+ add_defs_from_subschema(schema_hash, subschema)
176
+ add_refs_from_subschema(schema_hash, subschema)
73
177
  end
74
- schema[:defs] = definitions
75
178
  end
76
179
 
77
- def add_references(subschema)
78
- references = subschema.items.map do |item|
79
- { '$ref': item.ref_template }
180
+ ##
181
+ # For each item in the composer, add it to :defs so that we can reference it later.
182
+ #
183
+ def add_defs_from_subschema(schema_hash, subschema)
184
+ # Build up a hash of class_name => schema for each sub-item
185
+ definitions = subschema.items.each_with_object({}) do |item, acc|
186
+ acc[item.name] = item.schema
80
187
  end
81
- schema[subschema.name] = references
188
+ # Merge or create :defs
189
+ existing_defs = schema_hash[:defs] || {}
190
+ schema_hash[:defs] = existing_defs.merge(definitions)
82
191
  end
83
192
 
84
- def options
85
- @options = schema
86
- subschemas_from_schema_definition
87
- @options[:properties] = properties_from_schema_definition
88
- @options[:required] = @required_properties
89
- @options.reject! { |_key, value| [nil, [], {}].include?(value) }
90
- @options
193
+ ##
194
+ # Add references to the schema for each sub-item in the composer
195
+ # e.g. { "$ref": "#/$defs/SomeClass" }
196
+ #
197
+ def add_refs_from_subschema(schema_hash, subschema)
198
+ references = subschema.items.map { |item| { '$ref': item.ref_template } }
199
+ schema_hash[subschema.name] = references
91
200
  end
92
201
  end
93
202
  end
@@ -7,8 +7,6 @@ require 'active_support/time'
7
7
  require 'active_support/concern'
8
8
  require 'active_support/json'
9
9
  require 'active_model'
10
- require 'json_schemer'
11
- require_relative 'schema_errors_mapper'
12
10
  require_relative 'builders/object_builder'
13
11
  require_relative 'schema_definition'
14
12
 
@@ -39,30 +37,9 @@ module EasyTalk
39
37
  base.include ActiveModel::API # Include ActiveModel::API in the class including EasyTalk::Model
40
38
  base.include ActiveModel::Validations
41
39
  base.extend ActiveModel::Callbacks
42
- base.validates_with SchemaValidator
43
40
  base.extend(ClassMethods)
44
41
  end
45
42
 
46
- class SchemaValidator < ActiveModel::Validator
47
- def validate(record)
48
- result = schema_validation(record)
49
- result.errors.each do |key, error_msg|
50
- record.errors.add key.to_sym, error_msg
51
- end
52
- end
53
-
54
- def schema_validation(record)
55
- schema = JSONSchemer.schema(record.class.json_schema)
56
- errors = schema.validate(record.properties)
57
- SchemaErrorsMapper.new(errors)
58
- end
59
- end
60
-
61
- # Returns the properties of the model as a hash with symbolized keys.
62
- def properties
63
- as_json.symbolize_keys!
64
- end
65
-
66
43
  # Module containing class-level methods for defining and accessing the schema of a model.
67
44
  module ClassMethods
68
45
  # Returns the schema for the model.
@@ -72,13 +49,6 @@ module EasyTalk
72
49
  @schema ||= build_schema(schema_definition)
73
50
  end
74
51
 
75
- # Returns true if the class inherits a schema.
76
- #
77
- # @return [Boolean] `true` if the class inherits a schema, `false` otherwise.
78
- def inherits_schema?
79
- false
80
- end
81
-
82
52
  # Returns the reference template for the model.
83
53
  #
84
54
  # @return [String] The reference template for the model.
@@ -86,13 +56,6 @@ module EasyTalk
86
56
  "#/$defs/#{name}"
87
57
  end
88
58
 
89
- # Returns the name of the model as a human-readable function name.
90
- #
91
- # @return [String] The human-readable function name of the model.
92
- def function_name
93
- name.humanize.titleize
94
- end
95
-
96
59
  def properties
97
60
  @properties ||= begin
98
61
  return unless schema[:properties].present?
@@ -119,7 +82,7 @@ module EasyTalk
119
82
  @schema_definition.instance_eval(&block)
120
83
  attr_accessor(*properties)
121
84
 
122
- @schema_defintion
85
+ @schema_definition
123
86
  end
124
87
 
125
88
  # Returns the unvalidated schema definition for the model.
@@ -76,10 +76,16 @@ module EasyTalk
76
76
  #
77
77
  # @return [Object] The built property.
78
78
  def build
79
- return type.respond_to?(:schema) ? type.schema : 'object' unless builder
79
+ # return type.respond_to?(:schema) ? type.schema : 'object' unless builder
80
80
 
81
- args = builder.collection_type? ? [name, type, constraints] : [name, constraints]
82
- builder.new(*args).build
81
+ # args = builder.collection_type? ? [name, type, constraints] : [name, constraints]
82
+ # builder.new(*args).build
83
+ if builder
84
+ args = builder.collection_type? ? [name, type, constraints] : [name, constraints]
85
+ builder.new(*args).build
86
+ else
87
+ type.respond_to?(:schema) ? type.schema : 'object'
88
+ end
83
89
  end
84
90
 
85
91
  # Converts the object to a JSON representation.
@@ -97,7 +103,7 @@ module EasyTalk
97
103
  #
98
104
  # @return [Builder] The builder associated with the property type.
99
105
  def builder
100
- TYPE_TO_BUILDER[type.class.name.to_s] || TYPE_TO_BUILDER[type.name.to_s]
106
+ @builder ||= TYPE_TO_BUILDER[type.class.name.to_s] || TYPE_TO_BUILDER[type.name.to_s]
101
107
  end
102
108
  end
103
109
  end
@@ -3,12 +3,14 @@
3
3
  require_relative 'keywords'
4
4
 
5
5
  module EasyTalk
6
+ class InvalidPropertyNameError < StandardError; end
6
7
  #
7
8
  #= EasyTalk \SchemaDefinition
8
9
  # SchemaDefinition provides the methods for defining a schema within the define_schema block.
9
10
  # The @schema is a hash that contains the unvalidated schema definition for the model.
10
11
  # A SchemaDefinition instanace is the passed to the Builder.build_schema method to validate and compile the schema.
11
12
  class SchemaDefinition
13
+
12
14
  extend T::Sig
13
15
  extend T::AnyOf
14
16
  extend T::OneOf
@@ -35,18 +37,30 @@ module EasyTalk
35
37
  sig do
36
38
  params(name: T.any(Symbol, String), type: T.untyped, constraints: T.untyped, blk: T.nilable(T.proc.void)).void
37
39
  end
38
- def property(name, type, **constraints, &blk)
40
+ def property(name, type, constraints = {}, &blk)
41
+ validate_property_name(name)
39
42
  @schema[:properties] ||= {}
40
43
 
41
44
  if block_given?
42
- property_schema = SchemaDefinition.new(name, constraints)
45
+ property_schema = SchemaDefinition.new(name)
43
46
  property_schema.instance_eval(&blk)
44
- @schema[:properties][name] = property_schema
47
+
48
+ @schema[:properties][name] = {
49
+ type:,
50
+ constraints:,
51
+ properties: property_schema
52
+ }
45
53
  else
46
54
  @schema[:properties][name] = { type:, constraints: }
47
55
  end
48
56
  end
49
57
 
58
+ def validate_property_name(name)
59
+ unless name.to_s.match?(/^[A-Za-z_][A-Za-z0-9_]*$/)
60
+ raise InvalidPropertyNameError, "Invalid property name '#{name}'. Must start with letter/underscore and contain only letters, numbers, underscores"
61
+ end
62
+ end
63
+
50
64
  def optional?
51
65
  @schema[:optional]
52
66
  end
@@ -5,23 +5,35 @@ module EasyTalk
5
5
  # FunctionBuilder is a module that builds a hash with the function type and function details.
6
6
  # The return value is typically passed as argument to LLM function calling APIs.
7
7
  module FunctionBuilder
8
- # Creates a new function object based on the given model.
9
- #
10
- # @param [Model] model The EasyTalk model containing the function details.
11
- # @return [Hash] The function object.
12
- def self.new(model)
13
- {
14
- type: 'function',
15
- function: {
16
- name: model.function_name,
17
- description: generate_description(model),
18
- parameters: model.json_schema
8
+ class << self
9
+ # Creates a new function object based on the given model.
10
+ #
11
+ # @param [Model] model The EasyTalk model containing the function details.
12
+ # @return [Hash] The function object.
13
+ def new(model)
14
+ {
15
+ type: 'function',
16
+ function: {
17
+ name: generate_function_name(model),
18
+ description: generate_function_description(model),
19
+ parameters: model.json_schema
20
+ }
19
21
  }
20
- }
21
- end
22
+ end
23
+
24
+ def generate_function_name(model)
25
+ model.schema.fetch(:title, model.name)
26
+ end
27
+
28
+ def generate_function_description(model)
29
+ if model.respond_to?(:instructions)
30
+ raise Instructor::Error, 'The instructions must be a string' unless model.instructions.is_a?(String)
22
31
 
23
- def self.generate_description(model)
24
- "Correctly extracted `#{model.name}` with all the required parameters with correct types"
32
+ model.instructions
33
+ else
34
+ "Correctly extracted `#{model.name}` with all the required parameters and correct types."
35
+ end
36
+ end
25
37
  end
26
38
  end
27
39
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyTalk
4
- VERSION = '0.2.1'
4
+ VERSION = '1.0.0'
5
5
  end
metadata CHANGED
@@ -1,69 +1,54 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_talk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergio Bayona
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-05-06 00:00:00.000000000 Z
10
+ date: 2025-01-09 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activemodel
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
18
  version: '7.0'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - "~>"
23
+ - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '7.0'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '7.0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '7.0'
41
- - !ruby/object:Gem::Dependency
42
- name: json_schemer
43
28
  requirement: !ruby/object:Gem::Requirement
44
29
  requirements:
45
30
  - - ">="
46
31
  - !ruby/object:Gem::Version
47
- version: '0'
32
+ version: '7.0'
48
33
  type: :runtime
49
34
  prerelease: false
50
35
  version_requirements: !ruby/object:Gem::Requirement
51
36
  requirements:
52
37
  - - ">="
53
38
  - !ruby/object:Gem::Version
54
- version: '0'
39
+ version: '7.0'
55
40
  - !ruby/object:Gem::Dependency
56
41
  name: sorbet-runtime
57
42
  requirement: !ruby/object:Gem::Requirement
58
43
  requirements:
59
- - - "~>"
44
+ - - ">="
60
45
  - !ruby/object:Gem::Version
61
46
  version: '0.5'
62
47
  type: :runtime
63
48
  prerelease: false
64
49
  version_requirements: !ruby/object:Gem::Requirement
65
50
  requirements:
66
- - - "~>"
51
+ - - ">="
67
52
  - !ruby/object:Gem::Version
68
53
  version: '0.5'
69
54
  - !ruby/object:Gem::Dependency
@@ -84,98 +69,98 @@ dependencies:
84
69
  name: rake
85
70
  requirement: !ruby/object:Gem::Requirement
86
71
  requirements:
87
- - - "~>"
72
+ - - ">="
88
73
  - !ruby/object:Gem::Version
89
74
  version: '13.1'
90
75
  type: :development
91
76
  prerelease: false
92
77
  version_requirements: !ruby/object:Gem::Requirement
93
78
  requirements:
94
- - - "~>"
79
+ - - ">="
95
80
  - !ruby/object:Gem::Version
96
81
  version: '13.1'
97
82
  - !ruby/object:Gem::Dependency
98
83
  name: rspec
99
84
  requirement: !ruby/object:Gem::Requirement
100
85
  requirements:
101
- - - "~>"
86
+ - - ">="
102
87
  - !ruby/object:Gem::Version
103
88
  version: '3.0'
104
89
  type: :development
105
90
  prerelease: false
106
91
  version_requirements: !ruby/object:Gem::Requirement
107
92
  requirements:
108
- - - "~>"
93
+ - - ">="
109
94
  - !ruby/object:Gem::Version
110
95
  version: '3.0'
111
96
  - !ruby/object:Gem::Dependency
112
97
  name: rspec-json_expectations
113
98
  requirement: !ruby/object:Gem::Requirement
114
99
  requirements:
115
- - - "~>"
100
+ - - ">="
116
101
  - !ruby/object:Gem::Version
117
102
  version: '2.0'
118
103
  type: :development
119
104
  prerelease: false
120
105
  version_requirements: !ruby/object:Gem::Requirement
121
106
  requirements:
122
- - - "~>"
107
+ - - ">="
123
108
  - !ruby/object:Gem::Version
124
109
  version: '2.0'
125
110
  - !ruby/object:Gem::Dependency
126
111
  name: rspec-mocks
127
112
  requirement: !ruby/object:Gem::Requirement
128
113
  requirements:
129
- - - "~>"
114
+ - - ">="
130
115
  - !ruby/object:Gem::Version
131
116
  version: '3.13'
132
117
  type: :development
133
118
  prerelease: false
134
119
  version_requirements: !ruby/object:Gem::Requirement
135
120
  requirements:
136
- - - "~>"
121
+ - - ">="
137
122
  - !ruby/object:Gem::Version
138
123
  version: '3.13'
139
124
  - !ruby/object:Gem::Dependency
140
125
  name: rubocop
141
126
  requirement: !ruby/object:Gem::Requirement
142
127
  requirements:
143
- - - "~>"
128
+ - - ">="
144
129
  - !ruby/object:Gem::Version
145
130
  version: '1.21'
146
131
  type: :development
147
132
  prerelease: false
148
133
  version_requirements: !ruby/object:Gem::Requirement
149
134
  requirements:
150
- - - "~>"
135
+ - - ">="
151
136
  - !ruby/object:Gem::Version
152
137
  version: '1.21'
153
138
  - !ruby/object:Gem::Dependency
154
139
  name: rubocop-rake
155
140
  requirement: !ruby/object:Gem::Requirement
156
141
  requirements:
157
- - - "~>"
142
+ - - ">="
158
143
  - !ruby/object:Gem::Version
159
144
  version: '0.6'
160
145
  type: :development
161
146
  prerelease: false
162
147
  version_requirements: !ruby/object:Gem::Requirement
163
148
  requirements:
164
- - - "~>"
149
+ - - ">="
165
150
  - !ruby/object:Gem::Version
166
151
  version: '0.6'
167
152
  - !ruby/object:Gem::Dependency
168
153
  name: rubocop-rspec
169
154
  requirement: !ruby/object:Gem::Requirement
170
155
  requirements:
171
- - - "~>"
156
+ - - ">="
172
157
  - !ruby/object:Gem::Version
173
158
  version: '2.29'
174
159
  type: :development
175
160
  prerelease: false
176
161
  version_requirements: !ruby/object:Gem::Requirement
177
162
  requirements:
178
- - - "~>"
163
+ - - ">="
179
164
  - !ruby/object:Gem::Version
180
165
  version: '2.29'
181
166
  description: Generate json-schema from plain Ruby classes.
@@ -191,6 +176,13 @@ files:
191
176
  - LICENSE.txt
192
177
  - README.md
193
178
  - Rakefile
179
+ - docs/.gitignore
180
+ - docs/404.html
181
+ - docs/Gemfile
182
+ - docs/_config.yml
183
+ - docs/_posts/2024-05-07-welcome-to-jekyll.markdown
184
+ - docs/about.markdown
185
+ - docs/index.markdown
194
186
  - lib/easy_talk.rb
195
187
  - lib/easy_talk/builders/all_of_builder.rb
196
188
  - lib/easy_talk/builders/any_of_builder.rb
@@ -213,7 +205,6 @@ files:
213
205
  - lib/easy_talk/model.rb
214
206
  - lib/easy_talk/property.rb
215
207
  - lib/easy_talk/schema_definition.rb
216
- - lib/easy_talk/schema_errors_mapper.rb
217
208
  - lib/easy_talk/sorbet_extension.rb
218
209
  - lib/easy_talk/tools/function_builder.rb
219
210
  - lib/easy_talk/types/all_of.rb
@@ -229,7 +220,6 @@ metadata:
229
220
  homepage_uri: https://github.com/sergiobayona/easy_talk
230
221
  source_code_uri: https://github.com/sergiobayona/easy_talk
231
222
  changelog_uri: https://github.com/sergiobayona/easy_talk/blob/main/CHANGELOG.md
232
- post_install_message:
233
223
  rdoc_options: []
234
224
  require_paths:
235
225
  - lib
@@ -244,8 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
234
  - !ruby/object:Gem::Version
245
235
  version: '0'
246
236
  requirements: []
247
- rubygems_version: 3.5.9
248
- signing_key:
237
+ rubygems_version: 3.6.2
249
238
  specification_version: 4
250
239
  summary: Generate json-schema from Ruby classes.
251
240
  test_files: []
@@ -1,21 +0,0 @@
1
- module EasyTalk
2
- class SchemaErrorsMapper
3
- def initialize(errors)
4
- @errors = errors.to_a
5
- end
6
-
7
- def errors
8
- @errors.each_with_object({}) do |error, hash|
9
- if error['data_pointer'].present?
10
- key = error['data_pointer'].split('/').compact_blank.join('.')
11
- hash[key] = error['error']
12
- else
13
- error['details']['missing_keys'].each do |missing_key|
14
- message = "#{error['error'].split(':').first}: #{missing_key}"
15
- hash[missing_key] = message
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end