easy_talk 1.0.1 → 1.0.3
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 +51 -0
- data/README.md +767 -81
- data/lib/easy_talk/active_record_schema_builder.rb +292 -0
- data/lib/easy_talk/builders/base_builder.rb +16 -14
- data/lib/easy_talk/builders/object_builder.rb +10 -26
- data/lib/easy_talk/builders/string_builder.rb +1 -2
- data/lib/easy_talk/configuration.rb +27 -0
- data/lib/easy_talk/errors.rb +8 -0
- data/lib/easy_talk/errors_helper.rb +147 -0
- data/lib/easy_talk/model.rb +93 -2
- data/lib/easy_talk/property.rb +25 -1
- data/lib/easy_talk/schema_definition.rb +1 -2
- data/lib/easy_talk/version.rb +1 -1
- data/lib/easy_talk.rb +11 -3
- metadata +34 -2
data/lib/easy_talk/model.rb
CHANGED
@@ -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.
|
@@ -38,6 +39,55 @@ module EasyTalk
|
|
38
39
|
base.include ActiveModel::Validations
|
39
40
|
base.extend ActiveModel::Callbacks
|
40
41
|
base.extend(ClassMethods)
|
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)
|
48
|
+
end
|
49
|
+
|
50
|
+
module InstanceMethods
|
51
|
+
def initialize(attributes = {})
|
52
|
+
@additional_properties = {}
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(method_name, *args)
|
57
|
+
method_string = method_name.to_s
|
58
|
+
if method_string.end_with?('=')
|
59
|
+
property_name = method_string.chomp('=')
|
60
|
+
if self.class.additional_properties_allowed?
|
61
|
+
@additional_properties[property_name] = args.first
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
elsif self.class.additional_properties_allowed? && @additional_properties.key?(method_string)
|
66
|
+
@additional_properties[method_string]
|
67
|
+
else
|
68
|
+
super
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def respond_to_missing?(method_name, include_private = false)
|
73
|
+
method_string = method_name.to_s
|
74
|
+
method_string.end_with?('=') ? method_string.chomp('=') : method_string
|
75
|
+
self.class.additional_properties_allowed? || super
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add to_hash method to convert defined properties to hash
|
79
|
+
def to_hash
|
80
|
+
return {} unless self.class.properties
|
81
|
+
|
82
|
+
self.class.properties.each_with_object({}) do |prop, hash|
|
83
|
+
hash[prop.to_s] = send(prop)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Override as_json to include both defined and additional properties
|
88
|
+
def as_json(_options = {})
|
89
|
+
to_hash.merge(@additional_properties)
|
90
|
+
end
|
41
91
|
end
|
42
92
|
|
43
93
|
# Module containing class-level methods for defining and accessing the schema of a model.
|
@@ -46,7 +96,16 @@ module EasyTalk
|
|
46
96
|
#
|
47
97
|
# @return [Schema] The schema for the model.
|
48
98
|
def schema
|
49
|
-
@schema ||=
|
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
|
50
109
|
end
|
51
110
|
|
52
111
|
# Returns the reference template for the model.
|
@@ -92,9 +151,12 @@ module EasyTalk
|
|
92
151
|
@schema_definition ||= {}
|
93
152
|
end
|
94
153
|
|
95
|
-
|
154
|
+
def additional_properties_allowed?
|
155
|
+
@schema_definition&.schema&.fetch(:additional_properties, false)
|
156
|
+
end
|
96
157
|
|
97
158
|
# Builds the schema using the provided schema definition.
|
159
|
+
# This is the convergence point for all schema generation.
|
98
160
|
#
|
99
161
|
# @param schema_definition [SchemaDefinition] The schema definition.
|
100
162
|
# @return [Schema] The validated schema.
|
@@ -102,5 +164,34 @@ module EasyTalk
|
|
102
164
|
Builders::ObjectBuilder.new(schema_definition).build
|
103
165
|
end
|
104
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
|
105
196
|
end
|
106
197
|
end
|
data/lib/easy_talk/property.rb
CHANGED
@@ -76,7 +76,9 @@ module EasyTalk
|
|
76
76
|
#
|
77
77
|
# @return [Object] The built property.
|
78
78
|
def build
|
79
|
-
if
|
79
|
+
if nilable_type?
|
80
|
+
build_nilable_schema
|
81
|
+
elsif builder
|
80
82
|
args = builder.collection_type? ? [name, type, constraints] : [name, constraints]
|
81
83
|
builder.new(*args).build
|
82
84
|
elsif type.respond_to?(:schema)
|
@@ -105,5 +107,27 @@ module EasyTalk
|
|
105
107
|
def builder
|
106
108
|
@builder ||= TYPE_TO_BUILDER[type.class.name.to_s] || TYPE_TO_BUILDER[type.name.to_s]
|
107
109
|
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def nilable_type?
|
114
|
+
return unless type.respond_to?(:types)
|
115
|
+
return unless type.types.all? { |t| t.respond_to?(:raw_type) }
|
116
|
+
|
117
|
+
type.types.any? { |t| t.raw_type == NilClass }
|
118
|
+
end
|
119
|
+
|
120
|
+
def build_nilable_schema
|
121
|
+
# Extract the non-nil type from the Union
|
122
|
+
actual_type = type.types.find { |t| t != NilClass }
|
123
|
+
|
124
|
+
# Create a property with the actual type
|
125
|
+
non_nil_schema = Property.new(name, actual_type, constraints).build
|
126
|
+
|
127
|
+
# Merge the types into an array
|
128
|
+
non_nil_schema.merge(
|
129
|
+
type: [non_nil_schema[:type], 'null']
|
130
|
+
)
|
131
|
+
end
|
108
132
|
end
|
109
133
|
end
|
@@ -3,8 +3,6 @@
|
|
3
3
|
require_relative 'keywords'
|
4
4
|
|
5
5
|
module EasyTalk
|
6
|
-
class InvalidPropertyNameError < StandardError; end
|
7
|
-
|
8
6
|
#
|
9
7
|
#= EasyTalk \SchemaDefinition
|
10
8
|
# SchemaDefinition provides the methods for defining a schema within the define_schema block.
|
@@ -20,6 +18,7 @@ module EasyTalk
|
|
20
18
|
|
21
19
|
def initialize(name, schema = {})
|
22
20
|
@schema = schema
|
21
|
+
@schema[:additional_properties] = false unless schema.key?(:additional_properties)
|
23
22
|
@name = name
|
24
23
|
end
|
25
24
|
|
data/lib/easy_talk/version.rb
CHANGED
data/lib/easy_talk.rb
CHANGED
@@ -2,9 +2,11 @@
|
|
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'
|
7
|
+
require 'easy_talk/errors'
|
8
|
+
require 'easy_talk/errors_helper'
|
9
|
+
require 'easy_talk/configuration'
|
8
10
|
require 'easy_talk/types/any_of'
|
9
11
|
require 'easy_talk/types/all_of'
|
10
12
|
require 'easy_talk/types/one_of'
|
@@ -14,6 +16,12 @@ module EasyTalk
|
|
14
16
|
require 'easy_talk/tools/function_builder'
|
15
17
|
require 'easy_talk/version'
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
def self.assert_valid_property_options(property_name, options, *valid_keys)
|
20
|
+
valid_keys.flatten!
|
21
|
+
options.each_key do |k|
|
22
|
+
next if valid_keys.include?(k)
|
23
|
+
|
24
|
+
ErrorHelper.raise_unknown_option_error(property_name: property_name, option: options, valid_options: valid_keys)
|
25
|
+
end
|
26
|
+
end
|
19
27
|
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.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergio Bayona
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-11 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,6 +212,7 @@ files:
|
|
184
212
|
- docs/about.markdown
|
185
213
|
- docs/index.markdown
|
186
214
|
- lib/easy_talk.rb
|
215
|
+
- lib/easy_talk/active_record_schema_builder.rb
|
187
216
|
- lib/easy_talk/builders/all_of_builder.rb
|
188
217
|
- lib/easy_talk/builders/any_of_builder.rb
|
189
218
|
- lib/easy_talk/builders/base_builder.rb
|
@@ -201,6 +230,9 @@ files:
|
|
201
230
|
- lib/easy_talk/builders/time_builder.rb
|
202
231
|
- lib/easy_talk/builders/typed_array_builder.rb
|
203
232
|
- lib/easy_talk/builders/union_builder.rb
|
233
|
+
- lib/easy_talk/configuration.rb
|
234
|
+
- lib/easy_talk/errors.rb
|
235
|
+
- lib/easy_talk/errors_helper.rb
|
204
236
|
- lib/easy_talk/keywords.rb
|
205
237
|
- lib/easy_talk/model.rb
|
206
238
|
- lib/easy_talk/property.rb
|