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.
@@ -9,6 +9,7 @@ require 'active_support/json'
9
9
  require 'active_model'
10
10
  require_relative 'builders/object_builder'
11
11
  require_relative 'schema_definition'
12
+ require_relative 'active_record_schema_builder'
12
13
 
13
14
  module EasyTalk
14
15
  # The `Model` module is a mixin that provides functionality for defining and accessing the schema of a model.
@@ -39,6 +40,11 @@ module EasyTalk
39
40
  base.extend ActiveModel::Callbacks
40
41
  base.extend(ClassMethods)
41
42
  base.include(InstanceMethods)
43
+
44
+ # Apply ActiveRecord-specific functionality if appropriate
45
+ return unless defined?(ActiveRecord) && base.ancestors.include?(ActiveRecord::Base)
46
+
47
+ base.extend(ActiveRecordClassMethods)
42
48
  end
43
49
 
44
50
  module InstanceMethods
@@ -90,7 +96,16 @@ module EasyTalk
90
96
  #
91
97
  # @return [Schema] The schema for the model.
92
98
  def schema
93
- @schema ||= build_schema(schema_definition)
99
+ @schema ||= if defined?(@schema_definition) && @schema_definition
100
+ # Schema defined explicitly via define_schema
101
+ build_schema(@schema_definition)
102
+ elsif respond_to?(:active_record_schema_definition)
103
+ # ActiveRecord model without explicit schema definition
104
+ build_schema(active_record_schema_definition)
105
+ else
106
+ # Default case - empty schema
107
+ {}
108
+ end
94
109
  end
95
110
 
96
111
  # Returns the reference template for the model.
@@ -140,9 +155,8 @@ module EasyTalk
140
155
  @schema_definition&.schema&.fetch(:additional_properties, false)
141
156
  end
142
157
 
143
- private
144
-
145
158
  # Builds the schema using the provided schema definition.
159
+ # This is the convergence point for all schema generation.
146
160
  #
147
161
  # @param schema_definition [SchemaDefinition] The schema definition.
148
162
  # @return [Schema] The validated schema.
@@ -150,5 +164,34 @@ module EasyTalk
150
164
  Builders::ObjectBuilder.new(schema_definition).build
151
165
  end
152
166
  end
167
+
168
+ # Module containing ActiveRecord-specific methods for schema generation
169
+ module ActiveRecordClassMethods
170
+ # Gets a SchemaDefinition that's built from the ActiveRecord database schema
171
+ #
172
+ # @return [SchemaDefinition] A schema definition built from the database
173
+ def active_record_schema_definition
174
+ @active_record_schema_definition ||= ActiveRecordSchemaBuilder.new(self).build_schema_definition
175
+ end
176
+
177
+ # Store enhancements to be applied to the schema
178
+ #
179
+ # @return [Hash] The schema enhancements
180
+ def schema_enhancements
181
+ @schema_enhancements ||= {}
182
+ end
183
+
184
+ # Enhance the generated schema with additional information
185
+ #
186
+ # @param enhancements [Hash] The schema enhancements
187
+ # @return [void]
188
+ def enhance_schema(enhancements)
189
+ @schema_enhancements = enhancements
190
+ # Clear cached values to force regeneration
191
+ @active_record_schema_definition = nil
192
+ @schema = nil
193
+ @json_schema = nil
194
+ end
195
+ end
153
196
  end
154
197
  end
@@ -6,12 +6,8 @@ require_relative 'builders/number_builder'
6
6
  require_relative 'builders/boolean_builder'
7
7
  require_relative 'builders/null_builder'
8
8
  require_relative 'builders/string_builder'
9
- require_relative 'builders/date_builder'
10
- require_relative 'builders/datetime_builder'
11
- require_relative 'builders/time_builder'
12
- require_relative 'builders/any_of_builder'
13
- require_relative 'builders/all_of_builder'
14
- require_relative 'builders/one_of_builder'
9
+ require_relative 'builders/temporal_builder'
10
+ require_relative 'builders/composition_builder'
15
11
  require_relative 'builders/typed_array_builder'
16
12
  require_relative 'builders/union_builder'
17
13
 
@@ -40,12 +36,12 @@ module EasyTalk
40
36
  'BigDecimal' => Builders::NumberBuilder,
41
37
  'T::Boolean' => Builders::BooleanBuilder,
42
38
  'NilClass' => Builders::NullBuilder,
43
- 'Date' => Builders::DateBuilder,
44
- 'DateTime' => Builders::DatetimeBuilder,
45
- 'Time' => Builders::TimeBuilder,
46
- 'anyOf' => Builders::AnyOfBuilder,
47
- 'allOf' => Builders::AllOfBuilder,
48
- 'oneOf' => Builders::OneOfBuilder,
39
+ 'Date' => Builders::TemporalBuilder::DateBuilder,
40
+ 'DateTime' => Builders::TemporalBuilder::DatetimeBuilder,
41
+ 'Time' => Builders::TemporalBuilder::TimeBuilder,
42
+ 'anyOf' => Builders::CompositionBuilder::AnyOfBuilder,
43
+ 'allOf' => Builders::CompositionBuilder::AllOfBuilder,
44
+ 'oneOf' => Builders::CompositionBuilder::OneOfBuilder,
49
45
  'T::Types::TypedArray' => Builders::TypedArrayBuilder,
50
46
  'T::Types::Union' => Builders::UnionBuilder
51
47
  }.freeze
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'keywords'
4
+ require_relative 'types/composer'
4
5
 
5
6
  module EasyTalk
6
- class InvalidPropertyNameError < StandardError; end
7
-
8
7
  #
9
8
  #= EasyTalk \SchemaDefinition
10
9
  # SchemaDefinition provides the methods for defining a schema within the define_schema block.
@@ -20,6 +19,7 @@ module EasyTalk
20
19
 
21
20
  def initialize(name, schema = {})
22
21
  @schema = schema
22
+ @schema[:additional_properties] = false unless schema.key?(:additional_properties)
23
23
  @name = name
24
24
  end
25
25
 
@@ -65,5 +65,21 @@ module EasyTalk
65
65
  def optional?
66
66
  @schema[:optional]
67
67
  end
68
+
69
+ # Helper method for nullable and optional properties
70
+ def nullable_optional_property(name, type, constraints = {}, &blk)
71
+ # Ensure type is nilable
72
+ nilable_type = if type.respond_to?(:nilable?) && type.nilable?
73
+ type
74
+ else
75
+ T.nilable(type)
76
+ end
77
+
78
+ # Ensure constraints include optional: true
79
+ constraints = constraints.merge(optional: true)
80
+
81
+ # Call standard property method
82
+ property(name, nilable_type, constraints, &blk)
83
+ end
68
84
  end
69
85
  end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_composer'
4
+
5
+ module EasyTalk
6
+ module Types
7
+ # Base class for composition types
8
+ class Composer < BaseComposer
9
+ # Returns the name of the composition type.
10
+ def self.name
11
+ raise NotImplementedError, "#{self.class.name} must implement the name method"
12
+ end
13
+
14
+ # Returns the name of the composition type.
15
+ def name
16
+ self.class.name
17
+ end
18
+
19
+ # Represents a composition type that allows all of the specified types.
20
+ class AllOf < Composer
21
+ def self.name
22
+ :allOf
23
+ end
24
+
25
+ def name
26
+ :allOf
27
+ end
28
+ end
29
+
30
+ # Represents a composition type that allows any of the specified types.
31
+ class AnyOf < Composer
32
+ def self.name
33
+ :anyOf
34
+ end
35
+
36
+ def name
37
+ :anyOf
38
+ end
39
+ end
40
+
41
+ # Represents a composition type that allows one of the specified types.
42
+ class OneOf < Composer
43
+ def self.name
44
+ :oneOf
45
+ end
46
+
47
+ def name
48
+ :oneOf
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # Shorthand module for accessing the AllOf composer
56
+ module T
57
+ module AllOf
58
+ # Creates a new instance of `EasyTalk::Types::Composer::AllOf` with the given arguments.
59
+ #
60
+ # @param args [Array] the list of arguments to be passed to the constructor
61
+ # @return [EasyTalk::Types::Composer::AllOf] a new instance
62
+ def self.[](*args)
63
+ EasyTalk::Types::Composer::AllOf.new(*args)
64
+ end
65
+ end
66
+
67
+ # Shorthand module for accessing the AnyOf composer
68
+ module AnyOf
69
+ # Creates a new instance of `EasyTalk::Types::Composer::AnyOf` with the given arguments.
70
+ #
71
+ # @param args [Array] the list of arguments to be passed to the constructor
72
+ # @return [EasyTalk::Types::Composer::AnyOf] a new instance
73
+ def self.[](*args)
74
+ EasyTalk::Types::Composer::AnyOf.new(*args)
75
+ end
76
+ end
77
+
78
+ # Shorthand module for accessing the OneOf composer
79
+ module OneOf
80
+ # Creates a new instance of `EasyTalk::Types::Composer::OneOf` with the given arguments.
81
+ #
82
+ # @param args [Array] the list of arguments to be passed to the constructor
83
+ # @return [EasyTalk::Types::Composer::OneOf] a new instance
84
+ def self.[](*args)
85
+ EasyTalk::Types::Composer::OneOf.new(*args)
86
+ end
87
+ end
88
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyTalk
4
- VERSION = '1.0.2'
4
+ VERSION = '1.0.4'
5
5
  end
data/lib/easy_talk.rb CHANGED
@@ -2,18 +2,28 @@
2
2
 
3
3
  # The EasyTalk module is the main namespace for the gem.
4
4
  module EasyTalk
5
- class Error < StandardError; end
6
5
  require 'sorbet-runtime'
7
6
  require 'easy_talk/sorbet_extension'
8
- require 'easy_talk/types/any_of'
9
- require 'easy_talk/types/all_of'
10
- require 'easy_talk/types/one_of'
7
+ require 'easy_talk/errors'
8
+ require 'easy_talk/errors_helper'
9
+ require 'easy_talk/configuration'
10
+ require 'easy_talk/types/composer'
11
11
  require 'easy_talk/model'
12
12
  require 'easy_talk/property'
13
13
  require 'easy_talk/schema_definition'
14
14
  require 'easy_talk/tools/function_builder'
15
15
  require 'easy_talk/version'
16
16
 
17
- class UnsupportedTypeError < ArgumentError; end
18
- class UnsupportedConstraintError < ArgumentError; end
17
+ def self.assert_valid_property_options(property_name, options, *valid_keys)
18
+ valid_keys.flatten!
19
+ options.each_key do |k|
20
+ next if valid_keys.include?(k)
21
+
22
+ ErrorHelper.raise_unknown_option_error(property_name: property_name, option: options, valid_options: valid_keys)
23
+ end
24
+ end
25
+
26
+ def self.configure_nilable_behavior(nilable_is_optional = false)
27
+ configuration.nilable_is_optional = nilable_is_optional
28
+ end
19
29
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_talk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergio Bayona
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-13 00:00:00.000000000 Z
10
+ date: 2025-03-12 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activemodel
@@ -51,6 +51,20 @@ dependencies:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0.5'
54
+ - !ruby/object:Gem::Dependency
55
+ name: activerecord
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '7.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '7.0'
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: pry-byebug
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -163,6 +177,20 @@ dependencies:
163
177
  - - ">="
164
178
  - !ruby/object:Gem::Version
165
179
  version: '2.29'
180
+ - !ruby/object:Gem::Dependency
181
+ name: sqlite3
182
+ requirement: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '2'
187
+ type: :development
188
+ prerelease: false
189
+ version_requirements: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '2'
166
194
  description: Generate json-schema from plain Ruby classes.
167
195
  email:
168
196
  - bayona.sergio@gmail.com
@@ -184,33 +212,30 @@ files:
184
212
  - docs/about.markdown
185
213
  - docs/index.markdown
186
214
  - lib/easy_talk.rb
187
- - lib/easy_talk/builders/all_of_builder.rb
188
- - lib/easy_talk/builders/any_of_builder.rb
215
+ - lib/easy_talk/active_record_schema_builder.rb
189
216
  - lib/easy_talk/builders/base_builder.rb
190
217
  - lib/easy_talk/builders/boolean_builder.rb
191
218
  - lib/easy_talk/builders/collection_helpers.rb
192
219
  - lib/easy_talk/builders/composition_builder.rb
193
- - lib/easy_talk/builders/date_builder.rb
194
- - lib/easy_talk/builders/datetime_builder.rb
195
220
  - lib/easy_talk/builders/integer_builder.rb
196
221
  - lib/easy_talk/builders/null_builder.rb
197
222
  - lib/easy_talk/builders/number_builder.rb
198
223
  - lib/easy_talk/builders/object_builder.rb
199
- - lib/easy_talk/builders/one_of_builder.rb
200
224
  - lib/easy_talk/builders/string_builder.rb
201
- - lib/easy_talk/builders/time_builder.rb
225
+ - lib/easy_talk/builders/temporal_builder.rb
202
226
  - lib/easy_talk/builders/typed_array_builder.rb
203
227
  - lib/easy_talk/builders/union_builder.rb
228
+ - lib/easy_talk/configuration.rb
229
+ - lib/easy_talk/errors.rb
230
+ - lib/easy_talk/errors_helper.rb
204
231
  - lib/easy_talk/keywords.rb
205
232
  - lib/easy_talk/model.rb
206
233
  - lib/easy_talk/property.rb
207
234
  - lib/easy_talk/schema_definition.rb
208
235
  - lib/easy_talk/sorbet_extension.rb
209
236
  - lib/easy_talk/tools/function_builder.rb
210
- - lib/easy_talk/types/all_of.rb
211
- - lib/easy_talk/types/any_of.rb
212
237
  - lib/easy_talk/types/base_composer.rb
213
- - lib/easy_talk/types/one_of.rb
238
+ - lib/easy_talk/types/composer.rb
214
239
  - lib/easy_talk/version.rb
215
240
  homepage: https://github.com/sergiobayona/easy_talk
216
241
  licenses:
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'composition_builder'
4
-
5
- module EasyTalk
6
- module Builders
7
- # Builder class for integer properties.
8
- class AllOfBuilder < CompositionBuilder
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'composition_builder'
4
-
5
- module EasyTalk
6
- module Builders
7
- # Builder class for integer properties.
8
- class AnyOfBuilder < CompositionBuilder
9
- end
10
- end
11
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_builder'
4
-
5
- module EasyTalk
6
- module Builders
7
- # Builder class for date properties.
8
- class DateBuilder < StringBuilder
9
- # Modifies the schema to include the format constraint for a date property.
10
- sig { returns(T::Hash[Symbol, T.untyped]) }
11
- def schema
12
- super.tap do |schema|
13
- schema[:format] = 'date'
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_builder'
4
-
5
- module EasyTalk
6
- module Builders
7
- # Builder class for datetime properties.
8
- class DatetimeBuilder < StringBuilder
9
- # Modifies the schema to include the format constraint for a datetime property.
10
- sig { returns(T::Hash[Symbol, T.untyped]) }
11
- def schema
12
- super.tap do |schema|
13
- schema[:format] = 'date-time'
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'composition_builder'
4
-
5
- module EasyTalk
6
- module Builders
7
- # Builder class for integer properties.
8
- class OneOfBuilder < CompositionBuilder
9
- end
10
- end
11
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_builder'
4
-
5
- module EasyTalk
6
- module Builders
7
- # Builder class for time properties.
8
- class TimeBuilder < StringBuilder
9
- def schema
10
- super.tap do |schema|
11
- schema[:format] = 'time'
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_composer'
4
- # The EasyTalk module provides a collection of types for composing schemas.
5
- module EasyTalk
6
- # The `Types` module provides a collection of classes for composing different types.
7
- module Types
8
- # Represents a composition type that allows all of the specified types.
9
- class AllOf < BaseComposer
10
- def self.name
11
- :allOf
12
- end
13
-
14
- def name
15
- :allOf
16
- end
17
- end
18
- end
19
- end
20
-
21
- module T
22
- # no-doc
23
- module AllOf
24
- # Creates a new instance of `EasyTalk::Types::AllOf` with the given arguments.
25
- #
26
- # @param args [Array] the list of arguments to be passed to the `EasyTalk::Types::AllOf` constructor
27
- # @return [EasyTalk::Types::AllOf] a new instance of `EasyTalk::Types::AllOf`
28
- def self.[](*args)
29
- EasyTalk::Types::AllOf.new(*args)
30
- end
31
- end
32
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_composer'
4
- module EasyTalk
5
- module Types
6
- # The `Types` module provides a collection of composers for defining different types.
7
- #
8
- # This module contains composers for various types such as `AnyOf`, `AllOf`, etc.
9
- # Each composer is responsible for defining the behavior and properties of its respective type.
10
- class AnyOf < BaseComposer
11
- # Returns the name of the AnyOf composer.
12
- #
13
- # @return [Symbol] The name of the composer.
14
- def self.name
15
- :anyOf
16
- end
17
-
18
- # Returns the name of the AnyOf composer.
19
- #
20
- # @return [Symbol] The name of the composer.
21
- def name
22
- :anyOf
23
- end
24
- end
25
- end
26
- end
27
-
28
- module T
29
- # no-doc
30
- module AnyOf
31
- # Creates a new instance of `EasyTalk::Types::AnyOf` with the given arguments.
32
- #
33
- # @param args [Array] the list of arguments to be passed to the `EasyTalk::Types::AnyOf` constructor
34
- # @return [EasyTalk::Types::AnyOf] a new instance of `EasyTalk::Types::AnyOf`
35
- def self.[](*args)
36
- EasyTalk::Types::AnyOf.new(*args)
37
- end
38
- end
39
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_composer'
4
- module EasyTalk
5
- module Types
6
- # Represents a composition type that allows one of the specified types.
7
- class OneOf < BaseComposer
8
- # Returns the name of the composition type.
9
- def self.name
10
- :oneOf
11
- end
12
-
13
- # Returns the name of the composition type.
14
- def name
15
- :oneOf
16
- end
17
- end
18
- end
19
- end
20
-
21
- module T
22
- # Creates a new instance of `EasyTalk::Types::OneOf` with the given arguments.
23
- #
24
- # @param args [Array] the list of arguments to be passed to the `EasyTalk::Types::OneOf` constructor
25
- # @return [EasyTalk::Types::OneOf] a new instance of `EasyTalk::Types::OneOf`
26
- module OneOf
27
- def self.[](*args)
28
- EasyTalk::Types::OneOf.new(*args)
29
- end
30
- end
31
- end