easy_talk 0.1.10 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ebe87803e47220d1a3f6396a1735fd2aa04b3f2b1428bea43cd873cb32f3bca
4
- data.tar.gz: ecdaaa2801742335160a89a38a92ef9b402be563d3ce0e54c52f3068d75c93ce
3
+ metadata.gz: d3b84eeed5e8d6430c3bbaf97936ec90a29554dcbd71905553ecaf2f66b82877
4
+ data.tar.gz: 74fa329ca8574c8d8d8ec2b3daf6dee3a8d46a3550c53fb30ceb1709487243d9
5
5
  SHA512:
6
- metadata.gz: 866e44d124957d2149bd67584c0e35129bd922c98da0bb9d4b37cead66636d84b508290be35b4ce79ad3940bd556585ee604aeb79c220f898450624765e3fd50
7
- data.tar.gz: 551cd5c6f3de517efd56fadb407fd723de14764d3520b7be7ee73e12a7027d391816452ad13a00752e0fa690d5da2eef4aff2d0b12b585ed686eeb31635875ac
6
+ metadata.gz: 59be99a0311ec3c5d941e63cc2299e26d2a84c1a53ff88f6bd561dbd1b046dc3f4e5d68c8037724cd295df8d542a7a24621374cc535422920200a11ae66507e5
7
+ data.tar.gz: 2eabc32e703f00a68d47d1152fc1a42cc963e0f5ba05aea76b57b7ccccde670dcb4361811b8af812b85d2c78880f7b375e536d7ce7f0f12a7177dd8b80046775
data/.rubocop.yml CHANGED
@@ -27,4 +27,7 @@ Layout/LineLength:
27
27
 
28
28
  RSpec/DescribeClass:
29
29
  Exclude:
30
- - 'spec/easy_talk/examples/**/*'
30
+ - 'spec/easy_talk/examples/**/*'
31
+
32
+ RSpec/MultipleExpectations:
33
+ Max: 4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.2.1] - 2024-05-06
2
+ - Run JSON Schema validations using ActiveModel's validations.
3
+
4
+ ## [0.2.0] - 2024-05-01
5
+ - Added ActiveModel::API functionality to EasyTalk::Model module. That means you get all the benefits of ActiveModel::API including attribute assignment, introspections, validations, translation (i18n) and more. See https://api.rubyonrails.org/classes/ActiveModel/API.html for more information.
6
+
1
7
  ## [0.1.10] - 2024-04-29
2
8
  - Accept `:optional` key as constraint which excludes property from required node.
3
9
  - Spec fixes
data/README.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # EasyTalk
2
2
 
3
- EasyTalk is a Ruby library for defining and generating JSON Schema.
3
+ EasyTalk is a Ruby library that simplifies defining and generating JSON Schema documents, and validates that JSON data conforms to these schemas.
4
+
5
+ Key Features
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.
11
+
12
+ Inspiration
13
+ Inspired by Python's Pydantic library, EasyTalk brings similar functionality to the Ruby ecosystem, providing a Ruby-friendly approach to JSON Schema operations.
4
14
 
5
15
  Example Use:
6
16
 
@@ -41,6 +41,7 @@ module EasyTalk
41
41
  end
42
42
  end
43
43
 
44
+ # rubocop:disable Style/DoubleNegation
44
45
  def add_required_property(property_name, options)
45
46
  return if options.is_a?(Hash) && !!(options[:type].respond_to?(:nilable?) && options[:type].nilable?)
46
47
 
@@ -48,6 +49,7 @@ module EasyTalk
48
49
 
49
50
  @required_properties << property_name
50
51
  end
52
+ # rubocop:enable Style/DoubleNegation
51
53
 
52
54
  def build_property(property_name, options)
53
55
  if options.is_a?(EasyTalk::SchemaDefinition)
@@ -6,66 +6,56 @@ require 'active_support/core_ext'
6
6
  require 'active_support/time'
7
7
  require 'active_support/concern'
8
8
  require 'active_support/json'
9
- require 'json-schema'
9
+ require 'active_model'
10
+ require 'json_schemer'
11
+ require_relative 'schema_errors_mapper'
10
12
  require_relative 'builders/object_builder'
11
13
  require_relative 'schema_definition'
12
14
 
13
15
  module EasyTalk
14
- # The Model module can be included in a class to add JSON schema definition and generation support.
16
+ # The `Model` module is a mixin that provides functionality for defining and accessing the schema of a model.
17
+ #
18
+ # It includes methods for defining the schema, retrieving the schema definition,
19
+ # and generating the JSON schema for the model.
20
+ #
21
+ # Example usage:
22
+ #
23
+ # class Person
24
+ # include EasyTalk::Model
25
+ #
26
+ # define_schema do
27
+ # property :name, String, description: 'The person\'s name'
28
+ # property :age, Integer, description: 'The person\'s age'
29
+ # end
30
+ # end
31
+ #
32
+ # Person.json_schema #=> returns the JSON schema for Person
33
+ # jim = Person.new(name: 'Jim', age: 30)
34
+ # jim.valid? #=> returns true
35
+ #
36
+ # @see SchemaDefinition
15
37
  module Model
16
- # The `Model` module is a mixin that provides functionality for defining and accessing the schema of a model.
17
- #
18
- # It includes methods for defining the schema, retrieving the schema definition,
19
- # and generating the JSON schema for the model.
20
- #
21
- # Example usage:
22
- #
23
- # class MyModel
24
- # extend ClassMethods
25
- #
26
- # define_schema do
27
- # # schema definition goes here
28
- # end
29
- # end
30
- #
31
- # MyModel.json_schema #=> returns the JSON schema for MyModel
32
- #
33
- # MyModel.schema_definition #=> returns the unvalidated schema definition for MyModel
34
- #
35
- # MyModel.ref_template #=> returns the reference template for MyModel
36
- #
37
- # MyModel.inherits_schema? #=> returns false
38
- #
39
- # MyModel.schema #=> returns the validated schema for MyModel
40
- #
41
- # MyModel.schema_definition #=> returns the unvalidated schema definition for MyModel
42
- #
43
- # MyModel.json_schema #=> returns the JSON schema for MyModel
44
- #
45
- # @see SchemaDefinition
46
- #
47
38
  def self.included(base)
39
+ base.include ActiveModel::API # Include ActiveModel::API in the class including EasyTalk::Model
40
+ base.include ActiveModel::Validations
41
+ base.extend ActiveModel::Callbacks
42
+ base.validates_with SchemaValidator
48
43
  base.extend(ClassMethods)
49
44
  end
50
45
 
51
- # Initializes a new instance of the Model class.
52
- #
53
- # @param properties [Hash] The properties to set for the instance.
54
- def initialize(properties = {})
55
- properties.each do |key, value|
56
- instance_variable_set("@#{key}", value)
57
- self.class.class_eval { attr_reader key }
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
58
52
  end
59
- end
60
53
 
61
- # Checks if the model is valid.
62
- #
63
- # This method calls the `validate_json` class method on the current class,
64
- # passing the `properties` as the argument.
65
- #
66
- # @return [Boolean] true if the model is valid, false otherwise.
67
- def valid?
68
- self.class.validate_json(properties)
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
69
59
  end
70
60
 
71
61
  # Returns the properties of the model as a hash with symbolized keys.
@@ -103,12 +93,12 @@ module EasyTalk
103
93
  name.humanize.titleize
104
94
  end
105
95
 
106
- # Validates the given JSON against the model's JSON schema.
107
- #
108
- # @param json [Hash] The JSON to validate.
109
- # @return [Boolean] `true` if the JSON is valid, `false` otherwise.
110
- def validate_json(json)
111
- JSON::Validator.validate(json_schema, json)
96
+ def properties
97
+ @properties ||= begin
98
+ return unless schema[:properties].present?
99
+
100
+ schema[:properties].keys.map(&:to_sym)
101
+ end
112
102
  end
113
103
 
114
104
  # Returns the JSON schema for the model.
@@ -127,6 +117,9 @@ module EasyTalk
127
117
 
128
118
  @schema_definition = SchemaDefinition.new(name)
129
119
  @schema_definition.instance_eval(&block)
120
+ attr_accessor(*properties)
121
+
122
+ @schema_defintion
130
123
  end
131
124
 
132
125
  # Returns the unvalidated schema definition for the model.
@@ -0,0 +1,21 @@
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyTalk
4
- VERSION = '0.1.10'
4
+ VERSION = '0.2.1'
5
5
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_talk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergio Bayona
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-30 00:00:00.000000000 Z
11
+ date: 2024-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: activemodel
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
@@ -25,19 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '7.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: json-schema
28
+ name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '4'
33
+ version: '7.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '4'
40
+ version: '7.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json_schemer
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: sorbet-runtime
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -199,6 +213,7 @@ files:
199
213
  - lib/easy_talk/model.rb
200
214
  - lib/easy_talk/property.rb
201
215
  - lib/easy_talk/schema_definition.rb
216
+ - lib/easy_talk/schema_errors_mapper.rb
202
217
  - lib/easy_talk/sorbet_extension.rb
203
218
  - lib/easy_talk/tools/function_builder.rb
204
219
  - lib/easy_talk/types/all_of.rb