easy_talk 1.0.2 → 1.0.4
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/.rubocop.yml +6 -3
- data/CHANGELOG.md +32 -0
- data/README.md +907 -146
- data/lib/easy_talk/active_record_schema_builder.rb +295 -0
- data/lib/easy_talk/builders/base_builder.rb +16 -14
- data/lib/easy_talk/builders/composition_builder.rb +12 -0
- data/lib/easy_talk/builders/object_builder.rb +13 -2
- data/lib/easy_talk/builders/string_builder.rb +1 -2
- data/lib/easy_talk/builders/temporal_builder.rb +49 -0
- data/lib/easy_talk/configuration.rb +29 -0
- data/lib/easy_talk/errors.rb +8 -0
- data/lib/easy_talk/errors_helper.rb +147 -0
- data/lib/easy_talk/model.rb +46 -3
- data/lib/easy_talk/property.rb +8 -12
- data/lib/easy_talk/schema_definition.rb +18 -2
- data/lib/easy_talk/types/composer.rb +88 -0
- data/lib/easy_talk/version.rb +1 -1
- data/lib/easy_talk.rb +16 -6
- metadata +36 -11
- data/lib/easy_talk/builders/all_of_builder.rb +0 -11
- data/lib/easy_talk/builders/any_of_builder.rb +0 -11
- data/lib/easy_talk/builders/date_builder.rb +0 -18
- data/lib/easy_talk/builders/datetime_builder.rb +0 -18
- data/lib/easy_talk/builders/one_of_builder.rb +0 -11
- data/lib/easy_talk/builders/time_builder.rb +0 -16
- data/lib/easy_talk/types/all_of.rb +0 -32
- data/lib/easy_talk/types/any_of.rb +0 -39
- data/lib/easy_talk/types/one_of.rb +0 -31
data/README.md
CHANGED
@@ -1,41 +1,85 @@
|
|
1
1
|
# EasyTalk
|
2
2
|
|
3
|
-
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
### What is EasyTalk?
|
6
|
+
EasyTalk is a Ruby library that simplifies defining and generating JSON Schema. It provides an intuitive interface for Ruby developers to define structured data models that can be used for validation and documentation.
|
7
|
+
|
8
|
+
### Key Features
|
9
|
+
* **Intuitive Schema Definition**: Use Ruby classes and methods to define JSON Schema documents easily.
|
10
|
+
* **Works for plain Ruby classes and ActiveRecord models**: Integrate with existing code or build from scratch.
|
11
|
+
* **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.
|
12
|
+
* **Schema Composition**: Define EasyTalk models and reference them in other EasyTalk models to create complex schemas.
|
13
|
+
* **Validation**: Write validations using ActiveModel's validations.
|
14
|
+
|
15
|
+
### Use Cases
|
16
|
+
- API request/response validation
|
17
|
+
- LLM function definitions
|
18
|
+
- Object structure documentation
|
19
|
+
- Data validation and transformation
|
20
|
+
- Configuration schema definitions
|
21
|
+
|
22
|
+
### Inspiration
|
23
|
+
Inspired by Python's Pydantic library, EasyTalk brings similar functionality to the Ruby ecosystem, providing a Ruby-friendly approach to JSON Schema operations.
|
4
24
|
|
5
|
-
|
6
|
-
* Intuitive Schema Definition: Use Ruby classes and methods to define JSON Schema documents easily.
|
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 ActiveModel’s validations.
|
25
|
+
## Installation
|
10
26
|
|
11
|
-
|
12
|
-
|
27
|
+
### Requirements
|
28
|
+
- Ruby 3.2 or higher
|
29
|
+
- ActiveModel 7.0 or higher
|
30
|
+
- ActiveSupport 7.0 or higher
|
13
31
|
|
14
|
-
|
32
|
+
### Installation Steps
|
33
|
+
Add EasyTalk to your application's Gemfile:
|
15
34
|
|
16
35
|
```ruby
|
17
|
-
|
36
|
+
gem 'easy_talk'
|
37
|
+
```
|
38
|
+
|
39
|
+
Or install it directly:
|
40
|
+
|
41
|
+
```bash
|
42
|
+
$ gem install easy_talk
|
43
|
+
```
|
44
|
+
|
45
|
+
### Verification
|
46
|
+
After installation, you can verify it's working by creating a simple model:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'easy_talk'
|
50
|
+
|
51
|
+
class Test
|
18
52
|
include EasyTalk::Model
|
53
|
+
|
54
|
+
define_schema do
|
55
|
+
property :name, String
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
puts Test.json_schema
|
60
|
+
```
|
19
61
|
|
20
|
-
|
21
|
-
|
62
|
+
## Quick Start
|
63
|
+
|
64
|
+
### Minimal Example
|
65
|
+
Here's a basic example to get you started with EasyTalk:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class User
|
69
|
+
include EasyTalk::Model
|
22
70
|
|
23
71
|
define_schema do
|
24
72
|
title "User"
|
25
73
|
description "A user of the system"
|
26
|
-
property :name, String, description: "The user's name"
|
27
|
-
property :email,
|
28
|
-
|
29
|
-
property :verified, T::Boolean, description: "Whether the email is verified"
|
30
|
-
end
|
31
|
-
property :group, Integer, enum: [1, 2, 3], default: 1, description: "The user's group"
|
32
|
-
property :age, Integer, minimum: 18, maximum: 100, description: "The user's age"
|
33
|
-
property :tags, T::Array[String], min_items: 1, unique_items: true, description: "The user's tags"
|
74
|
+
property :name, String, description: "The user's name"
|
75
|
+
property :email, String, format: "email"
|
76
|
+
property :age, Integer, minimum: 18
|
34
77
|
end
|
35
78
|
end
|
36
79
|
```
|
37
80
|
|
38
|
-
|
81
|
+
### Generated JSON Schema
|
82
|
+
Calling `User.json_schema` will generate:
|
39
83
|
|
40
84
|
```ruby
|
41
85
|
{
|
@@ -44,89 +88,591 @@ Calling `User.json_schema` will return the Ruby representation of the JSON Schem
|
|
44
88
|
"description" => "A user of the system",
|
45
89
|
"properties" => {
|
46
90
|
"name" => {
|
47
|
-
"type" => "string",
|
91
|
+
"type" => "string",
|
92
|
+
"description" => "The user's name"
|
48
93
|
},
|
49
94
|
"email" => {
|
50
|
-
"type" => "
|
51
|
-
"
|
52
|
-
"address" => {
|
53
|
-
"type" => "string", "title" => "Email Address", "description" => "The user's email", "format" => "email"
|
54
|
-
},
|
55
|
-
"verified" => {
|
56
|
-
"type" => "boolean", "description" => "Whether the email is verified"
|
57
|
-
}
|
58
|
-
},
|
59
|
-
"required" => ["address", "verified"]
|
60
|
-
},
|
61
|
-
"group" => {
|
62
|
-
"type" => "integer", "description" => "The user's group", "enum" => [1, 2, 3], "default" => 1
|
95
|
+
"type" => "string",
|
96
|
+
"format" => "email"
|
63
97
|
},
|
64
98
|
"age" => {
|
65
|
-
"type" => "integer",
|
66
|
-
|
67
|
-
"tags" => {
|
68
|
-
"type" => "array",
|
69
|
-
"items" => { "type" => "string" },
|
70
|
-
"description" => "The user's tags",
|
71
|
-
"minItems" => 1,
|
72
|
-
"uniqueItems" => true
|
99
|
+
"type" => "integer",
|
100
|
+
"minimum" => 18
|
73
101
|
}
|
74
102
|
},
|
75
|
-
"required" => ["name", "email", "
|
103
|
+
"required" => ["name", "email", "age"]
|
76
104
|
}
|
77
105
|
```
|
78
106
|
|
79
|
-
|
107
|
+
### Basic Usage
|
108
|
+
Creating and validating an instance of your model:
|
80
109
|
|
81
110
|
```ruby
|
82
|
-
user = User.new(name: "John Doe", email:
|
111
|
+
user = User.new(name: "John Doe", email: "john@example.com", age: 25)
|
83
112
|
user.valid? # => true
|
84
113
|
|
85
|
-
user.
|
114
|
+
user.age = 17
|
86
115
|
user.valid? # => false
|
116
|
+
```
|
117
|
+
|
118
|
+
## Core Concepts
|
119
|
+
|
120
|
+
### Schema Definition
|
121
|
+
In EasyTalk, you define your schema by including the `EasyTalk::Model` module and using the `define_schema` method. This method takes a block where you can define the properties and constraints of your schema.
|
87
122
|
|
88
|
-
|
89
|
-
|
123
|
+
```ruby
|
124
|
+
class MyModel
|
125
|
+
include EasyTalk::Model
|
126
|
+
|
127
|
+
define_schema do
|
128
|
+
title "My Model"
|
129
|
+
description "Description of my model"
|
130
|
+
property :some_property, String
|
131
|
+
property :another_property, Integer
|
132
|
+
end
|
133
|
+
end
|
90
134
|
```
|
91
135
|
|
92
|
-
|
136
|
+
### Property Types
|
137
|
+
|
138
|
+
#### Ruby Types
|
139
|
+
EasyTalk supports standard Ruby types directly:
|
140
|
+
|
141
|
+
- `String`: String values
|
142
|
+
- `Integer`: Integer values
|
143
|
+
- `Float`: Floating-point numbers
|
144
|
+
- `Date`: Date values
|
145
|
+
- `DateTime`: Date and time values
|
146
|
+
- `Hash`: Object/dictionary values
|
147
|
+
|
148
|
+
#### Sorbet-Style Types
|
149
|
+
For complex types, EasyTalk uses Sorbet-style type notation:
|
150
|
+
|
151
|
+
- `T::Boolean`: Boolean values (true/false)
|
152
|
+
- `T::Array[Type]`: Arrays with items of a specific type
|
153
|
+
- `T.nilable(Type)`: Type that can also be nil
|
154
|
+
|
155
|
+
#### Custom Types
|
156
|
+
EasyTalk supports special composition types:
|
157
|
+
|
158
|
+
- `T::AnyOf[Type1, Type2, ...]`: Value can match any of the specified schemas
|
159
|
+
- `T::OneOf[Type1, Type2, ...]`: Value must match exactly one of the specified schemas
|
160
|
+
- `T::AllOf[Type1, Type2, ...]`: Value must match all of the specified schemas
|
161
|
+
|
162
|
+
### Property Constraints
|
163
|
+
Property constraints depend on the type of property. Some common constraints include:
|
164
|
+
|
165
|
+
- `description`: A description of the property
|
166
|
+
- `title`: A title for the property
|
167
|
+
- `format`: A format hint for the property (e.g., "email", "date")
|
168
|
+
- `enum`: A list of allowed values
|
169
|
+
- `minimum`/`maximum`: Minimum/maximum values for numbers
|
170
|
+
- `min_length`/`max_length`: Minimum/maximum length for strings
|
171
|
+
- `pattern`: A regular expression pattern for strings
|
172
|
+
- `min_items`/`max_items`: Minimum/maximum number of items for arrays
|
173
|
+
- `unique_items`: Whether array items must be unique
|
174
|
+
|
175
|
+
### Required vs Optional Properties
|
176
|
+
By default, all properties defined in an EasyTalk model are required. You can make a property optional by specifying `optional: true`:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
define_schema do
|
180
|
+
property :name, String
|
181
|
+
property :middle_name, String, optional: true
|
182
|
+
end
|
183
|
+
```
|
93
184
|
|
94
|
-
|
185
|
+
In this example, `name` is required but `middle_name` is optional.
|
95
186
|
|
96
|
-
|
187
|
+
### Schema Validation
|
188
|
+
EasyTalk models include ActiveModel validations. You can validate your models using the standard ActiveModel validation methods:
|
97
189
|
|
98
|
-
|
190
|
+
```ruby
|
191
|
+
class User
|
192
|
+
include EasyTalk::Model
|
193
|
+
|
194
|
+
validates :name, presence: true
|
195
|
+
validates :age, numericality: { greater_than_or_equal_to: 18 }
|
196
|
+
|
197
|
+
define_schema do
|
198
|
+
property :name, String
|
199
|
+
property :age, Integer, minimum: 18
|
200
|
+
end
|
201
|
+
end
|
99
202
|
|
100
|
-
|
203
|
+
user = User.new(name: "John", age: 17)
|
204
|
+
user.valid? # => false
|
205
|
+
user.errors.full_messages # => ["Age must be greater than or equal to 18"]
|
206
|
+
```
|
101
207
|
|
208
|
+
## Defining Schemas
|
102
209
|
|
103
|
-
|
210
|
+
### Basic Schema Structure
|
211
|
+
A schema definition consists of a class that includes `EasyTalk::Model` and a `define_schema` block:
|
104
212
|
|
105
|
-
|
213
|
+
```ruby
|
214
|
+
class Person
|
215
|
+
include EasyTalk::Model
|
106
216
|
|
107
|
-
|
108
|
-
|
109
|
-
|
217
|
+
define_schema do
|
218
|
+
title "Person"
|
219
|
+
property :name, String
|
220
|
+
property :age, Integer
|
221
|
+
end
|
222
|
+
end
|
223
|
+
```
|
110
224
|
|
111
|
-
|
225
|
+
### Property Definitions
|
226
|
+
Properties are defined using the `property` method, which takes a name, a type, and optional constraints:
|
112
227
|
|
113
|
-
|
228
|
+
```ruby
|
229
|
+
property :name, String, description: "The person's name", title: "Full Name"
|
230
|
+
property :age, Integer, minimum: 0, maximum: 120, description: "The person's age"
|
231
|
+
```
|
114
232
|
|
115
|
-
|
233
|
+
### Nested Objects
|
234
|
+
You can define nested objects using a block:
|
116
235
|
|
117
|
-
|
236
|
+
```ruby
|
237
|
+
property :email, Hash do
|
238
|
+
property :address, String, format: "email"
|
239
|
+
property :verified, T::Boolean
|
240
|
+
end
|
241
|
+
```
|
118
242
|
|
243
|
+
### Arrays and Collections
|
244
|
+
Arrays can be defined using the `T::Array` type:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
property :tags, T::Array[String], min_items: 1, unique_items: true
|
248
|
+
property :scores, T::Array[Integer], description: "List of scores"
|
249
|
+
```
|
250
|
+
|
251
|
+
You can also define arrays of complex types:
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
property :addresses, T::Array[Address], description: "List of addresses"
|
255
|
+
```
|
256
|
+
|
257
|
+
### Constraints and Validations
|
258
|
+
Constraints can be added to properties and are used for schema generation:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
property :name, String, min_length: 2, max_length: 50
|
262
|
+
property :email, String, format: "email"
|
263
|
+
property :category, String, enum: ["A", "B", "C"], default: "A"
|
264
|
+
```
|
265
|
+
|
266
|
+
For validation, you can use ActiveModel validations:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
validates :name, presence: true, length: { minimum: 2, maximum: 50 }
|
270
|
+
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
|
271
|
+
validates :category, inclusion: { in: ["A", "B", "C"] }
|
272
|
+
```
|
273
|
+
|
274
|
+
### Additional Properties
|
275
|
+
By default, EasyTalk models do not allow additional properties beyond those defined in the schema. You can change this behavior using the `additional_properties` keyword:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
define_schema do
|
279
|
+
property :name, String
|
280
|
+
additional_properties true
|
281
|
+
end
|
282
|
+
```
|
283
|
+
|
284
|
+
With `additional_properties true`, you can add arbitrary properties to your model instances:
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
company = Company.new
|
288
|
+
company.name = "Acme Corp" # Defined property
|
289
|
+
company.location = "New York" # Additional property
|
290
|
+
company.employee_count = 100 # Additional property
|
291
|
+
```
|
119
292
|
|
120
293
|
## Schema Composition
|
121
294
|
|
122
|
-
|
295
|
+
### Using T::AnyOf
|
296
|
+
The `T::AnyOf` type allows a property to match any of the specified schemas:
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
class Payment
|
300
|
+
include EasyTalk::Model
|
301
|
+
|
302
|
+
define_schema do
|
303
|
+
property :details, T::AnyOf[CreditCard, Paypal, BankTransfer]
|
304
|
+
end
|
305
|
+
end
|
306
|
+
```
|
307
|
+
|
308
|
+
### Using T::OneOf
|
309
|
+
The `T::OneOf` type requires a property to match exactly one of the specified schemas:
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
class Contact
|
313
|
+
include EasyTalk::Model
|
314
|
+
|
315
|
+
define_schema do
|
316
|
+
property :contact, T::OneOf[PhoneContact, EmailContact]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
```
|
320
|
+
|
321
|
+
### Using T::AllOf
|
322
|
+
The `T::AllOf` type requires a property to match all of the specified schemas:
|
323
|
+
|
324
|
+
```ruby
|
325
|
+
class VehicleRegistration
|
326
|
+
include EasyTalk::Model
|
327
|
+
|
328
|
+
define_schema do
|
329
|
+
compose T::AllOf[VehicleIdentification, OwnerInfo, RegistrationDetails]
|
330
|
+
end
|
331
|
+
end
|
332
|
+
```
|
333
|
+
|
334
|
+
### Complex Compositions
|
335
|
+
You can combine composition types to create complex schemas:
|
336
|
+
|
337
|
+
```ruby
|
338
|
+
class ComplexObject
|
339
|
+
include EasyTalk::Model
|
340
|
+
|
341
|
+
define_schema do
|
342
|
+
property :basic_info, BaseInfo
|
343
|
+
property :specific_details, T::OneOf[DetailTypeA, DetailTypeB]
|
344
|
+
property :metadata, T::AnyOf[AdminMetadata, UserMetadata, nil]
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
### Reusing Models
|
350
|
+
Models can reference other models to create hierarchical schemas:
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
class Address
|
354
|
+
include EasyTalk::Model
|
355
|
+
|
356
|
+
define_schema do
|
357
|
+
property :street, String
|
358
|
+
property :city, String
|
359
|
+
property :state, String
|
360
|
+
property :zip, String
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
class User
|
365
|
+
include EasyTalk::Model
|
366
|
+
|
367
|
+
define_schema do
|
368
|
+
property :name, String
|
369
|
+
property :address, Address
|
370
|
+
end
|
371
|
+
end
|
372
|
+
```
|
373
|
+
|
374
|
+
## ActiveModel Integration
|
375
|
+
|
376
|
+
### Validations
|
377
|
+
EasyTalk models include ActiveModel validations:
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
class User
|
381
|
+
include EasyTalk::Model
|
382
|
+
|
383
|
+
validates :age, comparison: { greater_than: 21 }
|
384
|
+
validates :height, presence: true, numericality: { greater_than: 0 }
|
385
|
+
|
386
|
+
define_schema do
|
387
|
+
property :name, String
|
388
|
+
property :age, Integer
|
389
|
+
property :height, Float
|
390
|
+
end
|
391
|
+
end
|
392
|
+
```
|
393
|
+
|
394
|
+
### Error Handling
|
395
|
+
You can access validation errors using the standard ActiveModel methods:
|
396
|
+
|
397
|
+
```ruby
|
398
|
+
user = User.new(name: "Jim", age: 18, height: -5.9)
|
399
|
+
user.valid? # => false
|
400
|
+
user.errors[:age] # => ["must be greater than 21"]
|
401
|
+
user.errors[:height] # => ["must be greater than 0"]
|
402
|
+
```
|
403
|
+
|
404
|
+
### Model Attributes
|
405
|
+
EasyTalk models provide getters and setters for all defined properties:
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
user = User.new
|
409
|
+
user.name = "John"
|
410
|
+
user.age = 30
|
411
|
+
puts user.name # => "John"
|
412
|
+
```
|
413
|
+
|
414
|
+
You can also initialize a model with a hash of attributes:
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
user = User.new(name: "John", age: 30, height: 5.9)
|
418
|
+
```
|
419
|
+
|
420
|
+
## ActiveRecord Integration
|
421
|
+
|
422
|
+
### Automatic Schema Generation
|
423
|
+
For ActiveRecord models, EasyTalk automatically generates a schema based on the database columns:
|
424
|
+
|
425
|
+
```ruby
|
426
|
+
class Product < ActiveRecord::Base
|
427
|
+
include EasyTalk::Model
|
428
|
+
end
|
429
|
+
```
|
430
|
+
|
431
|
+
This will create a schema with properties for each column in the `products` table.
|
432
|
+
|
433
|
+
### Enhancing Generated Schemas
|
434
|
+
You can enhance the auto-generated schema with the `enhance_schema` method:
|
435
|
+
|
436
|
+
```ruby
|
437
|
+
class Product < ActiveRecord::Base
|
438
|
+
include EasyTalk::Model
|
439
|
+
|
440
|
+
enhance_schema({
|
441
|
+
title: "Retail Product",
|
442
|
+
description: "A product available for purchase",
|
443
|
+
properties: {
|
444
|
+
name: {
|
445
|
+
description: "Product display name",
|
446
|
+
title: "Product Name"
|
447
|
+
},
|
448
|
+
price: {
|
449
|
+
description: "Retail price in USD"
|
450
|
+
}
|
451
|
+
}
|
452
|
+
})
|
453
|
+
end
|
454
|
+
```
|
455
|
+
|
456
|
+
### Column Exclusion Options
|
457
|
+
EasyTalk provides several ways to exclude columns from your JSON schema:
|
458
|
+
|
459
|
+
#### 1. Global Configuration
|
460
|
+
|
461
|
+
```ruby
|
462
|
+
EasyTalk.configure do |config|
|
463
|
+
# Exclude specific columns by name from all models
|
464
|
+
config.excluded_columns = [:created_at, :updated_at, :deleted_at]
|
465
|
+
|
466
|
+
# Exclude all foreign key columns (columns ending with '_id')
|
467
|
+
config.exclude_foreign_keys = true # Default: false
|
468
|
+
|
469
|
+
# Exclude all primary key columns ('id')
|
470
|
+
config.exclude_primary_key = true # Default: true
|
471
|
+
|
472
|
+
# Exclude timestamp columns ('created_at', 'updated_at')
|
473
|
+
config.exclude_timestamps = true # Default: true
|
474
|
+
|
475
|
+
# Exclude all association properties
|
476
|
+
config.exclude_associations = true # Default: false
|
477
|
+
end
|
478
|
+
```
|
479
|
+
|
480
|
+
#### 2. Model-Specific Column Ignoring
|
481
|
+
|
482
|
+
```ruby
|
483
|
+
class Product < ActiveRecord::Base
|
484
|
+
include EasyTalk::Model
|
485
|
+
|
486
|
+
enhance_schema({
|
487
|
+
ignore: [:internal_ref_id, :legacy_code] # Model-specific exclusions
|
488
|
+
})
|
489
|
+
end
|
490
|
+
```
|
491
|
+
|
492
|
+
### Virtual Properties
|
493
|
+
You can add properties that don't exist as database columns:
|
494
|
+
|
495
|
+
```ruby
|
496
|
+
class Product < ActiveRecord::Base
|
497
|
+
include EasyTalk::Model
|
498
|
+
|
499
|
+
enhance_schema({
|
500
|
+
properties: {
|
501
|
+
full_details: {
|
502
|
+
virtual: true,
|
503
|
+
type: :string,
|
504
|
+
description: "Complete product information"
|
505
|
+
}
|
506
|
+
}
|
507
|
+
})
|
508
|
+
end
|
509
|
+
```
|
510
|
+
|
511
|
+
### Associations and Foreign Keys
|
512
|
+
By default, EasyTalk includes your model's associations in the schema:
|
513
|
+
|
514
|
+
```ruby
|
515
|
+
class Product < ActiveRecord::Base
|
516
|
+
include EasyTalk::Model
|
517
|
+
belongs_to :category
|
518
|
+
has_many :reviews
|
519
|
+
end
|
520
|
+
```
|
521
|
+
|
522
|
+
This will include `category` (as an object) and `reviews` (as an array) in the schema.
|
523
|
+
|
524
|
+
You can control this behavior with configuration:
|
525
|
+
|
526
|
+
```ruby
|
527
|
+
EasyTalk.configure do |config|
|
528
|
+
config.exclude_associations = true # Don't include associations
|
529
|
+
config.exclude_foreign_keys = true # Don't include foreign key columns
|
530
|
+
end
|
531
|
+
```
|
532
|
+
|
533
|
+
## Advanced Features
|
534
|
+
|
535
|
+
### LLM Function Generation
|
536
|
+
EasyTalk provides a helper method for generating OpenAI function specifications:
|
537
|
+
|
538
|
+
```ruby
|
539
|
+
class Weather
|
540
|
+
include EasyTalk::Model
|
541
|
+
|
542
|
+
define_schema do
|
543
|
+
title "GetWeather"
|
544
|
+
description "Get the current weather in a given location"
|
545
|
+
property :location, String, description: "The city and state, e.g. San Francisco, CA"
|
546
|
+
property :unit, String, enum: ["celsius", "fahrenheit"], default: "fahrenheit"
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
function_spec = EasyTalk::Tools::FunctionBuilder.new(Weather)
|
551
|
+
```
|
552
|
+
|
553
|
+
This generates a function specification compatible with OpenAI's function calling API.
|
554
|
+
|
555
|
+
### Schema Transformation
|
556
|
+
You can transform EasyTalk schemas into various formats:
|
557
|
+
|
558
|
+
```ruby
|
559
|
+
# Get Ruby hash representation
|
560
|
+
schema_hash = User.schema
|
561
|
+
|
562
|
+
# Get JSON Schema representation
|
563
|
+
json_schema = User.json_schema
|
564
|
+
|
565
|
+
# Convert to JSON string
|
566
|
+
json_string = User.json_schema.to_json
|
567
|
+
```
|
568
|
+
|
569
|
+
### Type Checking and Validation
|
570
|
+
EasyTalk performs basic type checking during schema definition:
|
571
|
+
|
572
|
+
```ruby
|
573
|
+
# This will raise an error because "minimum" should be used with numeric types
|
574
|
+
property :name, String, minimum: 1 # Error!
|
575
|
+
|
576
|
+
# This will raise an error because enum values must match the property type
|
577
|
+
property :age, Integer, enum: ["young", "old"] # Error!
|
578
|
+
```
|
579
|
+
|
580
|
+
### Custom Type Builders
|
581
|
+
For advanced use cases, you can create custom type builders:
|
582
|
+
|
583
|
+
```ruby
|
584
|
+
module EasyTalk
|
585
|
+
module Builders
|
586
|
+
class MyCustomTypeBuilder < BaseBuilder
|
587
|
+
# Custom implementation
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
```
|
592
|
+
|
593
|
+
## Configuration
|
594
|
+
|
595
|
+
### Global Settings
|
596
|
+
You can configure EasyTalk globally:
|
123
597
|
|
124
|
-
|
125
|
-
|
126
|
-
|
598
|
+
```ruby
|
599
|
+
EasyTalk.configure do |config|
|
600
|
+
config.excluded_columns = [:created_at, :updated_at, :deleted_at]
|
601
|
+
config.exclude_foreign_keys = true
|
602
|
+
config.exclude_primary_key = true
|
603
|
+
config.exclude_timestamps = true
|
604
|
+
config.exclude_associations = false
|
605
|
+
config.default_additional_properties = false
|
606
|
+
end
|
607
|
+
```
|
608
|
+
|
609
|
+
### Per-Model Configuration
|
610
|
+
Some settings can be configured per model:
|
611
|
+
|
612
|
+
```ruby
|
613
|
+
class Product < ActiveRecord::Base
|
614
|
+
include EasyTalk::Model
|
615
|
+
|
616
|
+
enhance_schema({
|
617
|
+
additionalProperties: true,
|
618
|
+
ignore: [:internal_ref_id, :legacy_code]
|
619
|
+
})
|
620
|
+
end
|
621
|
+
```
|
622
|
+
|
623
|
+
### Exclusion Rules
|
624
|
+
Columns are excluded based on the following rules (in order of precedence):
|
625
|
+
|
626
|
+
1. Explicitly listed in `excluded_columns` global setting
|
627
|
+
2. Listed in the model's `schema_enhancements[:ignore]` array
|
628
|
+
3. Is a primary key when `exclude_primary_key` is true (default)
|
629
|
+
4. Is a timestamp column when `exclude_timestamps` is true (default)
|
630
|
+
5. Matches a foreign key pattern when `exclude_foreign_keys` is true
|
631
|
+
|
632
|
+
### Customizing Output
|
633
|
+
You can customize the JSON Schema output by enhancing the schema:
|
634
|
+
|
635
|
+
```ruby
|
636
|
+
class User < ActiveRecord::Base
|
637
|
+
include EasyTalk::Model
|
638
|
+
|
639
|
+
enhance_schema({
|
640
|
+
title: "User Account",
|
641
|
+
description: "User account information",
|
642
|
+
properties: {
|
643
|
+
name: {
|
644
|
+
title: "Full Name",
|
645
|
+
description: "User's full name"
|
646
|
+
}
|
647
|
+
}
|
648
|
+
})
|
649
|
+
end
|
650
|
+
```
|
127
651
|
|
128
|
-
|
652
|
+
## Examples
|
129
653
|
|
654
|
+
### User Registration
|
655
|
+
|
656
|
+
```ruby
|
657
|
+
class User
|
658
|
+
include EasyTalk::Model
|
659
|
+
|
660
|
+
validates :name, :email, :password, presence: true
|
661
|
+
validates :password, length: { minimum: 8 }
|
662
|
+
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
|
663
|
+
|
664
|
+
define_schema do
|
665
|
+
title "User Registration"
|
666
|
+
description "User registration information"
|
667
|
+
property :name, String, description: "User's full name"
|
668
|
+
property :email, String, format: "email", description: "User's email address"
|
669
|
+
property :password, String, min_length: 8, description: "User's password"
|
670
|
+
property :notify, T::Boolean, default: true, description: "Whether to send notifications"
|
671
|
+
end
|
672
|
+
end
|
673
|
+
```
|
674
|
+
|
675
|
+
### Payment Processing
|
130
676
|
|
131
677
|
```ruby
|
132
678
|
class CreditCard
|
@@ -176,131 +722,328 @@ class Payment
|
|
176
722
|
end
|
177
723
|
```
|
178
724
|
|
179
|
-
|
725
|
+
### Complex Object Hierarchies
|
726
|
+
|
727
|
+
```ruby
|
728
|
+
class Address
|
729
|
+
include EasyTalk::Model
|
180
730
|
|
181
|
-
|
731
|
+
define_schema do
|
732
|
+
property :street, String
|
733
|
+
property :city, String
|
734
|
+
property :state, String
|
735
|
+
property :zip, String, pattern: '^[0-9]{5}(?:-[0-9]{4})?$'
|
736
|
+
end
|
737
|
+
end
|
182
738
|
|
183
|
-
|
739
|
+
class Employee
|
740
|
+
include EasyTalk::Model
|
184
741
|
|
185
|
-
|
742
|
+
define_schema do
|
743
|
+
title 'Employee'
|
744
|
+
description 'Company employee'
|
745
|
+
property :name, String, title: 'Full Name'
|
746
|
+
property :gender, String, enum: %w[male female other]
|
747
|
+
property :department, T.nilable(String)
|
748
|
+
property :hire_date, Date
|
749
|
+
property :active, T::Boolean, default: true
|
750
|
+
property :addresses, T.nilable(T::Array[Address])
|
751
|
+
end
|
752
|
+
end
|
186
753
|
|
187
|
-
```ruby
|
188
754
|
class Company
|
189
755
|
include EasyTalk::Model
|
190
756
|
|
191
757
|
define_schema do
|
758
|
+
title 'Company'
|
192
759
|
property :name, String
|
193
|
-
|
760
|
+
property :employees, T::Array[Employee], title: 'Company Employees', description: 'A list of company employees'
|
194
761
|
end
|
195
762
|
end
|
763
|
+
```
|
196
764
|
|
197
|
-
|
198
|
-
company = Company.new
|
199
|
-
company.name = "Acme Corp" # Defined property
|
200
|
-
company.location = "New York" # Additional property
|
201
|
-
company.employee_count = 100 # Additional property
|
765
|
+
### API Integration
|
202
766
|
|
203
|
-
|
204
|
-
#
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
767
|
+
```ruby
|
768
|
+
# app/controllers/api/users_controller.rb
|
769
|
+
class Api::UsersController < ApplicationController
|
770
|
+
def create
|
771
|
+
schema = User.json_schema
|
772
|
+
|
773
|
+
# Validate incoming request against the schema
|
774
|
+
validation_result = JSONSchemer.schema(schema).valid?(params.to_json)
|
775
|
+
|
776
|
+
if validation_result
|
777
|
+
user = User.new(user_params)
|
778
|
+
if user.save
|
779
|
+
render json: user, status: :created
|
780
|
+
else
|
781
|
+
render json: { errors: user.errors }, status: :unprocessable_entity
|
782
|
+
end
|
783
|
+
else
|
784
|
+
render json: { errors: "Invalid request" }, status: :bad_request
|
785
|
+
end
|
786
|
+
end
|
787
|
+
|
788
|
+
private
|
789
|
+
|
790
|
+
def user_params
|
791
|
+
params.require(:user).permit(:name, :email, :password)
|
792
|
+
end
|
793
|
+
end
|
209
794
|
```
|
210
795
|
|
211
|
-
|
796
|
+
## Troubleshooting
|
212
797
|
|
213
|
-
|
214
|
-
- Instances can accept properties beyond those defined in the schema
|
215
|
-
- Additional properties can be set both via the constructor and direct assignment
|
216
|
-
- Additional properties are included in JSON serialization
|
217
|
-
- Attempting to access an undefined additional property raises NoMethodError
|
798
|
+
### Common Errors
|
218
799
|
|
219
|
-
|
220
|
-
|
221
|
-
company = Company.new(
|
222
|
-
name: "Acme Corp",
|
223
|
-
location: "New York" # Additional property
|
224
|
-
)
|
800
|
+
#### "Invalid property name"
|
801
|
+
Property names must start with a letter or underscore and can only contain letters, numbers, and underscores:
|
225
802
|
|
226
|
-
|
227
|
-
|
803
|
+
```ruby
|
804
|
+
# Invalid
|
805
|
+
property "1name", String # Starts with a number
|
806
|
+
property "name!", String # Contains a special character
|
228
807
|
|
229
|
-
#
|
230
|
-
|
808
|
+
# Valid
|
809
|
+
property :name, String
|
810
|
+
property :user_name, String
|
231
811
|
```
|
232
812
|
|
233
|
-
|
234
|
-
|
235
|
-
- Attempting to set or get undefined properties raises NoMethodError
|
813
|
+
#### "Property type is missing"
|
814
|
+
You must specify a type for each property:
|
236
815
|
|
237
816
|
```ruby
|
238
|
-
|
239
|
-
|
817
|
+
# Invalid
|
818
|
+
property :name
|
240
819
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
820
|
+
# Valid
|
821
|
+
property :name, String
|
822
|
+
```
|
823
|
+
|
824
|
+
#### "Unknown option"
|
825
|
+
You specified an option that is not valid for the property type:
|
826
|
+
|
827
|
+
```ruby
|
828
|
+
# Invalid (min_length is for strings, not integers)
|
829
|
+
property :age, Integer, min_length: 2
|
246
830
|
|
247
|
-
|
248
|
-
|
249
|
-
company.location = "New York" # Raises NoMethodError
|
831
|
+
# Valid
|
832
|
+
property :age, Integer, minimum: 18
|
250
833
|
```
|
251
834
|
|
252
|
-
###
|
835
|
+
### Schema Validation Issues
|
836
|
+
If you're having issues with validation:
|
253
837
|
|
254
|
-
|
838
|
+
1. Make sure you've defined ActiveModel validations for your model
|
839
|
+
2. Check for mismatches between schema constraints and validations
|
840
|
+
3. Verify that required properties are present
|
841
|
+
|
842
|
+
### Type Errors
|
843
|
+
Type errors usually occur when there's a mismatch between a property type and its constraints:
|
255
844
|
|
256
845
|
```ruby
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
#
|
261
|
-
|
262
|
-
# },
|
263
|
-
# "required" => ["name"],
|
264
|
-
# "additionalProperties" => true
|
265
|
-
# }
|
846
|
+
# Error: enum values must be strings for a string property
|
847
|
+
property :status, String, enum: [1, 2, 3]
|
848
|
+
|
849
|
+
# Correct
|
850
|
+
property :status, String, enum: ["active", "inactive", "pending"]
|
266
851
|
```
|
267
852
|
|
268
853
|
### Best Practices
|
269
854
|
|
270
|
-
1.
|
855
|
+
1. Define clear property names and descriptions
|
856
|
+
2. Use appropriate types for each property
|
857
|
+
3. Add validations for important business rules
|
858
|
+
4. Keep schemas focused and modular
|
859
|
+
5. Reuse models when appropriate
|
860
|
+
6. Use explicit types instead of relying on inference
|
861
|
+
7. Test your schemas with sample data
|
862
|
+
|
863
|
+
# Nullable vs Optional Properties in EasyTalk
|
271
864
|
|
272
|
-
|
865
|
+
One of the most important distinctions when defining schemas is understanding the difference between **nullable** properties and **optional** properties. This guide explains these concepts and how to use them effectively in EasyTalk.
|
273
866
|
|
274
|
-
|
867
|
+
## Key Concepts
|
275
868
|
|
276
|
-
|
869
|
+
| Concept | Description | JSON Schema Effect | EasyTalk Syntax |
|
870
|
+
|---------|-------------|-------------------|-----------------|
|
871
|
+
| **Nullable** | Property can have a `null` value | Adds `"null"` to the type array | `T.nilable(Type)` |
|
872
|
+
| **Optional** | Property doesn't have to exist | Omits property from `"required"` array | `optional: true` constraint |
|
873
|
+
|
874
|
+
## Nullable Properties
|
875
|
+
|
876
|
+
A **nullable** property can contain a `null` value, but the property itself must still be present in the object:
|
277
877
|
|
278
878
|
```ruby
|
279
|
-
|
280
|
-
value = company.try(:optional_property)
|
281
|
-
# or
|
282
|
-
value = company.optional_property if company.respond_to?(:optional_property)
|
879
|
+
property :age, T.nilable(Integer)
|
283
880
|
```
|
284
881
|
|
285
|
-
|
882
|
+
This produces the following JSON Schema:
|
286
883
|
|
287
|
-
|
884
|
+
```json
|
885
|
+
{
|
886
|
+
"properties": {
|
887
|
+
"age": { "type": ["integer", "null"] }
|
888
|
+
},
|
889
|
+
"required": ["age"]
|
890
|
+
}
|
891
|
+
```
|
288
892
|
|
289
|
-
|
290
|
-
|
893
|
+
In this case, the following data would be valid:
|
894
|
+
- `{ "age": 25 }`
|
895
|
+
- `{ "age": null }`
|
291
896
|
|
292
|
-
|
897
|
+
But this would be invalid:
|
898
|
+
- `{ }` (missing the age property entirely)
|
293
899
|
|
294
|
-
|
900
|
+
## Optional Properties
|
295
901
|
|
296
|
-
|
902
|
+
An **optional** property doesn't have to be present in the object at all:
|
297
903
|
|
298
|
-
|
904
|
+
```ruby
|
905
|
+
property :nickname, String, optional: true
|
906
|
+
```
|
299
907
|
|
300
|
-
|
908
|
+
This produces:
|
909
|
+
|
910
|
+
```json
|
911
|
+
{
|
912
|
+
"properties": {
|
913
|
+
"nickname": { "type": "string" }
|
914
|
+
}
|
915
|
+
// Note: "nickname" is not in the "required" array
|
916
|
+
}
|
917
|
+
```
|
918
|
+
|
919
|
+
In this case, the following data would be valid:
|
920
|
+
- `{ "nickname": "Joe" }`
|
921
|
+
- `{ }` (omitting nickname entirely)
|
922
|
+
|
923
|
+
But this would be invalid:
|
924
|
+
- `{ "nickname": null }` (null is not allowed because the property isn't nullable)
|
301
925
|
|
302
|
-
##
|
926
|
+
## Nullable AND Optional Properties
|
303
927
|
|
928
|
+
For properties that should be both nullable and optional (can be omitted or null), you need to combine both approaches:
|
929
|
+
|
930
|
+
```ruby
|
931
|
+
property :bio, T.nilable(String), optional: true
|
932
|
+
```
|
933
|
+
|
934
|
+
This produces:
|
935
|
+
|
936
|
+
```json
|
937
|
+
{
|
938
|
+
"properties": {
|
939
|
+
"bio": { "type": ["string", "null"] }
|
940
|
+
}
|
941
|
+
// Note: "bio" is not in the "required" array
|
942
|
+
}
|
943
|
+
```
|
944
|
+
|
945
|
+
For convenience, EasyTalk also provides a helper method:
|
946
|
+
|
947
|
+
```ruby
|
948
|
+
nullable_optional_property :bio, String
|
949
|
+
```
|
950
|
+
|
951
|
+
Which is equivalent to the above.
|
952
|
+
|
953
|
+
## Configuration Options
|
954
|
+
|
955
|
+
By default, nullable properties are still required. You can change this global behavior:
|
956
|
+
|
957
|
+
```ruby
|
958
|
+
EasyTalk.configure do |config|
|
959
|
+
config.nilable_is_optional = true # Makes all T.nilable properties also optional
|
960
|
+
end
|
961
|
+
```
|
962
|
+
|
963
|
+
With this configuration, any property defined with `T.nilable(Type)` will be treated as both nullable and optional.
|
964
|
+
|
965
|
+
## Practical Examples
|
966
|
+
|
967
|
+
### User Profile Schema
|
968
|
+
|
969
|
+
```ruby
|
970
|
+
class UserProfile
|
971
|
+
include EasyTalk::Model
|
972
|
+
|
973
|
+
define_schema do
|
974
|
+
# Required properties (must exist, cannot be null)
|
975
|
+
property :id, String
|
976
|
+
property :name, String
|
977
|
+
|
978
|
+
# Required but nullable (must exist, can be null)
|
979
|
+
property :age, T.nilable(Integer)
|
980
|
+
|
981
|
+
# Optional but not nullable (can be omitted, cannot be null if present)
|
982
|
+
property :email, String, optional: true
|
983
|
+
|
984
|
+
# Optional and nullable (can be omitted, can be null if present)
|
985
|
+
nullable_optional_property :bio, String
|
986
|
+
|
987
|
+
# Nested object with mixed property types
|
988
|
+
property :address, Hash do
|
989
|
+
property :street, String # Required
|
990
|
+
property :city, String # Required
|
991
|
+
property :state, String, optional: true # Optional
|
992
|
+
nullable_optional_property :zip, String # Optional and nullable
|
993
|
+
end
|
994
|
+
end
|
995
|
+
end
|
996
|
+
```
|
997
|
+
|
998
|
+
This creates clear expectations for data validation:
|
999
|
+
- `id` and `name` must be present and cannot be null
|
1000
|
+
- `age` must be present but can be null
|
1001
|
+
- `email` doesn't have to be present, but if it is, it cannot be null
|
1002
|
+
- `bio` doesn't have to be present, and if it is, it can be null
|
1003
|
+
|
1004
|
+
## Common Gotchas
|
1005
|
+
|
1006
|
+
### Misconception: Nullable Implies Optional
|
1007
|
+
|
1008
|
+
A common mistake is assuming that `T.nilable(Type)` makes a property optional. By default, it only allows the property to have a null value - the property itself is still required to exist in the object.
|
1009
|
+
|
1010
|
+
### Misconception: Optional Properties Accept Null
|
1011
|
+
|
1012
|
+
An optional property (defined with `optional: true`) can be omitted entirely, but if it is present, it must conform to its type constraint. If you want to allow null values, you must also make it nullable with `T.nilable(Type)`.
|
1013
|
+
|
1014
|
+
## Migration from Earlier Versions
|
1015
|
+
|
1016
|
+
If you're upgrading from EasyTalk version 1.0.1 or earlier, be aware that the handling of nullable vs optional properties has been improved for clarity.
|
1017
|
+
|
1018
|
+
To maintain backward compatibility with your existing code, you can use:
|
1019
|
+
|
1020
|
+
```ruby
|
1021
|
+
EasyTalk.configure do |config|
|
1022
|
+
config.nilable_is_optional = true # Makes T.nilable properties behave as they did before
|
1023
|
+
end
|
1024
|
+
```
|
1025
|
+
|
1026
|
+
We recommend updating your schema definitions to explicitly declare which properties are optional using the `optional: true` constraint, as this makes your intent clearer.
|
1027
|
+
|
1028
|
+
## Best Practices
|
1029
|
+
|
1030
|
+
1. **Be explicit about intent**: Always clarify whether properties should be nullable, optional, or both
|
1031
|
+
2. **Use the helper method**: For properties that are both nullable and optional, use `nullable_optional_property`
|
1032
|
+
3. **Document expectations**: Use comments to clarify validation requirements for complex schemas
|
1033
|
+
4. **Consider validation implications**: Remember that ActiveModel validations operate independently of the schema definition
|
1034
|
+
|
1035
|
+
## JSON Schema Comparison
|
1036
|
+
|
1037
|
+
| EasyTalk Definition | Required | Nullable | JSON Schema Equivalent |
|
1038
|
+
|--------------------|----------|----------|------------------------|
|
1039
|
+
| `property :p, String` | Yes | No | `{ "properties": { "p": { "type": "string" } }, "required": ["p"] }` |
|
1040
|
+
| `property :p, T.nilable(String)` | Yes | Yes | `{ "properties": { "p": { "type": ["string", "null"] } }, "required": ["p"] }` |
|
1041
|
+
| `property :p, String, optional: true` | No | No | `{ "properties": { "p": { "type": "string" } } }` |
|
1042
|
+
| `nullable_optional_property :p, String` | No | Yes | `{ "properties": { "p": { "type": ["string", "null"] } } }` |
|
1043
|
+
|
1044
|
+
## Development and Contributing
|
1045
|
+
|
1046
|
+
### Setting Up the Development Environment
|
304
1047
|
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.
|
305
1048
|
|
306
1049
|
To install this gem onto your local machine, run:
|
@@ -309,11 +1052,29 @@ To install this gem onto your local machine, run:
|
|
309
1052
|
bundle exec rake install
|
310
1053
|
```
|
311
1054
|
|
312
|
-
|
1055
|
+
### Running Tests
|
1056
|
+
Run the test suite with:
|
1057
|
+
|
1058
|
+
```bash
|
1059
|
+
bundle exec rake spec
|
1060
|
+
```
|
1061
|
+
|
1062
|
+
### Contributing Guidelines
|
1063
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sergiobayona/easy_talk.
|
1064
|
+
|
1065
|
+
## JSON Schema Compatibility
|
1066
|
+
|
1067
|
+
### Supported Versions
|
1068
|
+
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.
|
313
1069
|
|
314
|
-
|
1070
|
+
### Specification Compliance
|
1071
|
+
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.
|
1072
|
+
|
1073
|
+
### Known Limitations
|
1074
|
+
- Limited support for custom formats
|
1075
|
+
- No direct support for JSON Schema draft 2020-12 features
|
1076
|
+
- Complex composition scenarios may require manual adjustment
|
315
1077
|
|
316
1078
|
## License
|
317
1079
|
|
318
1080
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
319
|
-
|