easy_talk 3.1.0 → 3.3.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 +4 -4
- data/.rubocop.yml +15 -39
- data/.yardopts +13 -0
- data/CHANGELOG.md +164 -0
- data/README.md +442 -1529
- data/Rakefile +27 -0
- data/docs/.gitignore +1 -0
- data/docs/about.markdown +28 -8
- data/docs/getting-started.markdown +102 -0
- data/docs/index.markdown +51 -4
- data/docs/json_schema_compliance.md +169 -0
- data/docs/nested-models.markdown +216 -0
- data/docs/primitive-schema-rfc.md +894 -0
- data/docs/property-types.markdown +212 -0
- data/docs/schema-definition.markdown +180 -0
- data/lib/easy_talk/builders/base_builder.rb +6 -3
- data/lib/easy_talk/builders/boolean_builder.rb +2 -1
- data/lib/easy_talk/builders/collection_helpers.rb +4 -0
- data/lib/easy_talk/builders/composition_builder.rb +16 -13
- data/lib/easy_talk/builders/integer_builder.rb +2 -1
- data/lib/easy_talk/builders/null_builder.rb +4 -1
- data/lib/easy_talk/builders/number_builder.rb +4 -1
- data/lib/easy_talk/builders/object_builder.rb +109 -33
- data/lib/easy_talk/builders/registry.rb +182 -0
- data/lib/easy_talk/builders/string_builder.rb +3 -1
- data/lib/easy_talk/builders/temporal_builder.rb +7 -0
- data/lib/easy_talk/builders/tuple_builder.rb +89 -0
- data/lib/easy_talk/builders/typed_array_builder.rb +19 -6
- data/lib/easy_talk/builders/union_builder.rb +5 -1
- data/lib/easy_talk/configuration.rb +47 -2
- data/lib/easy_talk/error_formatter/base.rb +100 -0
- data/lib/easy_talk/error_formatter/error_code_mapper.rb +82 -0
- data/lib/easy_talk/error_formatter/flat.rb +38 -0
- data/lib/easy_talk/error_formatter/json_pointer.rb +38 -0
- data/lib/easy_talk/error_formatter/jsonapi.rb +64 -0
- data/lib/easy_talk/error_formatter/path_converter.rb +53 -0
- data/lib/easy_talk/error_formatter/rfc7807.rb +69 -0
- data/lib/easy_talk/error_formatter.rb +143 -0
- data/lib/easy_talk/errors.rb +3 -0
- data/lib/easy_talk/errors_helper.rb +66 -34
- data/lib/easy_talk/json_schema_equality.rb +46 -0
- data/lib/easy_talk/keywords.rb +0 -1
- data/lib/easy_talk/model.rb +148 -89
- data/lib/easy_talk/model_helper.rb +17 -0
- data/lib/easy_talk/naming_strategies.rb +24 -0
- data/lib/easy_talk/property.rb +23 -94
- data/lib/easy_talk/ref_helper.rb +33 -0
- data/lib/easy_talk/schema.rb +199 -0
- data/lib/easy_talk/schema_definition.rb +57 -5
- data/lib/easy_talk/schema_methods.rb +111 -0
- data/lib/easy_talk/sorbet_extension.rb +1 -0
- data/lib/easy_talk/tools/function_builder.rb +1 -1
- data/lib/easy_talk/type_introspection.rb +222 -0
- data/lib/easy_talk/types/base_composer.rb +2 -1
- data/lib/easy_talk/types/composer.rb +4 -0
- data/lib/easy_talk/types/tuple.rb +77 -0
- data/lib/easy_talk/validation_adapters/active_model_adapter.rb +617 -0
- data/lib/easy_talk/validation_adapters/active_model_schema_validation.rb +106 -0
- data/lib/easy_talk/validation_adapters/base.rb +156 -0
- data/lib/easy_talk/validation_adapters/none_adapter.rb +45 -0
- data/lib/easy_talk/validation_adapters/registry.rb +87 -0
- data/lib/easy_talk/validation_builder.rb +29 -309
- data/lib/easy_talk/version.rb +1 -1
- data/lib/easy_talk.rb +42 -0
- metadata +38 -7
- data/docs/404.html +0 -25
- data/docs/_posts/2024-05-07-welcome-to-jekyll.markdown +0 -29
- data/easy_talk.gemspec +0 -39
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EasyTalk
|
|
4
|
+
module ValidationAdapters
|
|
5
|
+
# ActiveModel-specific schema-level validations for object-level constraints.
|
|
6
|
+
#
|
|
7
|
+
# This module provides ActiveModel validations for JSON Schema keywords that apply
|
|
8
|
+
# to the object as a whole rather than individual properties:
|
|
9
|
+
# - minProperties: minimum number of properties that must be present
|
|
10
|
+
# - maxProperties: maximum number of properties that can be present
|
|
11
|
+
# - dependentRequired: conditional property requirements
|
|
12
|
+
#
|
|
13
|
+
# This module is tightly coupled with ActiveModel and is used exclusively by
|
|
14
|
+
# ActiveModelAdapter. Other validation adapters should implement their own
|
|
15
|
+
# schema-level validation logic.
|
|
16
|
+
#
|
|
17
|
+
module ActiveModelSchemaValidation
|
|
18
|
+
# Apply all applicable schema-level validations.
|
|
19
|
+
#
|
|
20
|
+
# @param klass [Class] The model class to apply validations to
|
|
21
|
+
# @param schema [Hash] The full schema hash containing schema-level constraints
|
|
22
|
+
# @return [void]
|
|
23
|
+
def self.apply(klass, schema)
|
|
24
|
+
apply_min_properties_validation(klass, schema[:min_properties]) if schema[:min_properties]
|
|
25
|
+
apply_max_properties_validation(klass, schema[:max_properties]) if schema[:max_properties]
|
|
26
|
+
apply_dependent_required_validation(klass, schema[:dependent_required]) if schema[:dependent_required]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Apply minimum properties validation.
|
|
30
|
+
#
|
|
31
|
+
# @param klass [Class] The model class
|
|
32
|
+
# @param min_count [Integer] Minimum number of properties that must be present
|
|
33
|
+
def self.apply_min_properties_validation(klass, min_count)
|
|
34
|
+
define_count_method(klass)
|
|
35
|
+
|
|
36
|
+
klass.validate do |record|
|
|
37
|
+
present_count = record.send(:count_present_properties)
|
|
38
|
+
if present_count < min_count
|
|
39
|
+
record.errors.add(:base, "must have at least #{min_count} #{min_count == 1 ? 'property' : 'properties'} present")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Apply maximum properties validation.
|
|
45
|
+
#
|
|
46
|
+
# @param klass [Class] The model class
|
|
47
|
+
# @param max_count [Integer] Maximum number of properties that can be present
|
|
48
|
+
def self.apply_max_properties_validation(klass, max_count)
|
|
49
|
+
define_count_method(klass)
|
|
50
|
+
|
|
51
|
+
klass.validate do |record|
|
|
52
|
+
present_count = record.send(:count_present_properties)
|
|
53
|
+
if present_count > max_count
|
|
54
|
+
record.errors.add(:base, "must have at most #{max_count} #{max_count == 1 ? 'property' : 'properties'} present")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Apply dependent required validation.
|
|
60
|
+
# When a trigger property is present, all dependent properties must also be present.
|
|
61
|
+
#
|
|
62
|
+
# @param klass [Class] The model class
|
|
63
|
+
# @param dependencies [Hash<String, Array<String>>] Map of trigger properties to required properties
|
|
64
|
+
def self.apply_dependent_required_validation(klass, dependencies)
|
|
65
|
+
dependencies.each do |trigger_property, required_properties|
|
|
66
|
+
trigger_prop = trigger_property.to_sym
|
|
67
|
+
required_props = required_properties.map(&:to_sym)
|
|
68
|
+
|
|
69
|
+
klass.validate do |record|
|
|
70
|
+
trigger_value = record.public_send(trigger_prop)
|
|
71
|
+
trigger_present = trigger_value.present? || trigger_value == false
|
|
72
|
+
|
|
73
|
+
next unless trigger_present
|
|
74
|
+
|
|
75
|
+
required_props.each do |required_prop|
|
|
76
|
+
value = record.public_send(required_prop)
|
|
77
|
+
value_present = value.present? || value == false
|
|
78
|
+
|
|
79
|
+
record.errors.add(required_prop, "is required when #{trigger_prop} is present") unless value_present
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Define the count_present_properties private instance method on the class if not already defined.
|
|
86
|
+
# The method counts how many schema properties have non-nil/non-blank values.
|
|
87
|
+
#
|
|
88
|
+
# @param klass [Class] The model class
|
|
89
|
+
def self.define_count_method(klass)
|
|
90
|
+
# Check for private methods as well with the second argument
|
|
91
|
+
return if klass.method_defined?(:count_present_properties, true)
|
|
92
|
+
|
|
93
|
+
klass.send(:define_method, :count_present_properties) do
|
|
94
|
+
schema_props = self.class.schema_definition.schema[:properties] || {}
|
|
95
|
+
schema_props.keys.count do |prop|
|
|
96
|
+
value = public_send(prop)
|
|
97
|
+
value.present? || value == false # false is a valid present value
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
klass.send(:private, :count_present_properties)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private_class_method :define_count_method
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EasyTalk
|
|
4
|
+
module ValidationAdapters
|
|
5
|
+
# Abstract base class for validation adapters.
|
|
6
|
+
#
|
|
7
|
+
# Validation adapters are responsible for converting JSON Schema constraints
|
|
8
|
+
# into validation rules for the target validation framework (e.g., ActiveModel,
|
|
9
|
+
# dry-validation, or custom validators).
|
|
10
|
+
#
|
|
11
|
+
# To create a custom adapter, subclass this class and implement the
|
|
12
|
+
# `apply_validations` method.
|
|
13
|
+
#
|
|
14
|
+
# @example Creating a custom adapter
|
|
15
|
+
# class MyCustomAdapter < EasyTalk::ValidationAdapters::Base
|
|
16
|
+
# def apply_validations
|
|
17
|
+
# # Apply custom validations to @klass based on @constraints
|
|
18
|
+
# @klass.validates @property_name, presence: true unless optional?
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# @example Registering and using a custom adapter
|
|
23
|
+
# EasyTalk::ValidationAdapters::Registry.register(:custom, MyCustomAdapter)
|
|
24
|
+
#
|
|
25
|
+
# class User
|
|
26
|
+
# include EasyTalk::Model
|
|
27
|
+
# define_schema(validations: :custom) do
|
|
28
|
+
# property :name, String
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
class Base
|
|
33
|
+
# Build validations for a property and apply them to the model class.
|
|
34
|
+
# This is the primary interface that adapters must implement.
|
|
35
|
+
#
|
|
36
|
+
# @param klass [Class] The model class to apply validations to
|
|
37
|
+
# @param property_name [Symbol, String] The name of the property
|
|
38
|
+
# @param type [Class, Object] The type of the property (Ruby class or Sorbet type)
|
|
39
|
+
# @param constraints [Hash] The JSON Schema constraints for the property
|
|
40
|
+
# Possible keys: :min_length, :max_length, :minimum, :maximum, :pattern,
|
|
41
|
+
# :format, :enum, :const, :min_items, :max_items, :unique_items, :optional
|
|
42
|
+
# @return [void]
|
|
43
|
+
def self.build_validations(klass, property_name, type, constraints)
|
|
44
|
+
new(klass, property_name, type, constraints).apply_validations
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Build schema-level validations (e.g., min_properties, max_properties, dependent_required).
|
|
48
|
+
# Subclasses can override this method to implement schema-level validations.
|
|
49
|
+
#
|
|
50
|
+
# @param klass [Class] The model class to apply validations to
|
|
51
|
+
# @param schema [Hash] The full schema hash containing schema-level constraints
|
|
52
|
+
# @return [void]
|
|
53
|
+
def self.build_schema_validations(klass, schema)
|
|
54
|
+
# Default implementation does nothing - subclasses can override
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Initialize a new validation adapter instance.
|
|
58
|
+
#
|
|
59
|
+
# @param klass [Class] The model class to apply validations to
|
|
60
|
+
# @param property_name [Symbol, String] The name of the property
|
|
61
|
+
# @param type [Class, Object] The type of the property
|
|
62
|
+
# @param constraints [Hash] The JSON Schema constraints for the property
|
|
63
|
+
def initialize(klass, property_name, type, constraints)
|
|
64
|
+
@klass = klass
|
|
65
|
+
@property_name = property_name.to_sym
|
|
66
|
+
@type = type
|
|
67
|
+
@constraints = constraints || {}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Apply validations based on property type and constraints.
|
|
71
|
+
# Subclasses MUST implement this method.
|
|
72
|
+
#
|
|
73
|
+
# @abstract
|
|
74
|
+
# @return [void]
|
|
75
|
+
# @raise [NotImplementedError] if the subclass does not implement this method
|
|
76
|
+
def apply_validations
|
|
77
|
+
raise NotImplementedError, "#{self.class} must implement #apply_validations"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
protected
|
|
81
|
+
|
|
82
|
+
attr_reader :klass, :property_name, :type, :constraints
|
|
83
|
+
|
|
84
|
+
# Check if a property is optional based on constraints and configuration.
|
|
85
|
+
#
|
|
86
|
+
# A property is considered optional if:
|
|
87
|
+
# - The :optional constraint is explicitly set to true
|
|
88
|
+
# - The type is nilable AND nilable_is_optional configuration is true
|
|
89
|
+
#
|
|
90
|
+
# @return [Boolean] true if the property is optional
|
|
91
|
+
def optional?
|
|
92
|
+
@constraints[:optional] == true ||
|
|
93
|
+
(@type.respond_to?(:nilable?) && @type.nilable? && EasyTalk.configuration.nilable_is_optional)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Check if the type is nilable (e.g., T.nilable(String)).
|
|
97
|
+
#
|
|
98
|
+
# @param t [Class, Object] The type to check (defaults to @type)
|
|
99
|
+
# @return [Boolean] true if the type is nilable
|
|
100
|
+
def nilable_type?(type_to_check = @type)
|
|
101
|
+
type_to_check.respond_to?(:nilable?) && type_to_check.nilable?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Extract the inner type from a complex type like T.nilable(String) or T.nilable(T::Array[Model]).
|
|
105
|
+
#
|
|
106
|
+
# @param type_to_unwrap [Class, Object] The type to unwrap (defaults to @type)
|
|
107
|
+
# @return [Class, Object] The inner type, or the original type if not wrapped
|
|
108
|
+
def extract_inner_type(type_to_unwrap = @type)
|
|
109
|
+
if type_to_unwrap.respond_to?(:unwrap_nilable)
|
|
110
|
+
unwrapped = type_to_unwrap.unwrap_nilable
|
|
111
|
+
# Return TypedArray directly (for T.nilable(T::Array[Model]))
|
|
112
|
+
return unwrapped if unwrapped.is_a?(T::Types::TypedArray)
|
|
113
|
+
# Return raw_type for simple types (for T.nilable(String))
|
|
114
|
+
return unwrapped.raw_type if unwrapped.respond_to?(:raw_type)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if type_to_unwrap.respond_to?(:types)
|
|
118
|
+
# For union types, find the non-nil type
|
|
119
|
+
# Prefer TypedArray if present, otherwise find type with raw_type
|
|
120
|
+
type_to_unwrap.types.find { |t| t.is_a?(T::Types::TypedArray) } ||
|
|
121
|
+
type_to_unwrap.types.find { |t| t.respond_to?(:raw_type) && t.raw_type != NilClass }
|
|
122
|
+
else
|
|
123
|
+
type_to_unwrap
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Determine the actual class for a type, handling Sorbet types.
|
|
128
|
+
#
|
|
129
|
+
# @param type_to_resolve [Class, Object] The type to resolve
|
|
130
|
+
# @return [Class, Array<Class>] The resolved class or classes
|
|
131
|
+
def get_type_class(type_to_resolve)
|
|
132
|
+
if type_to_resolve.is_a?(Class)
|
|
133
|
+
type_to_resolve
|
|
134
|
+
elsif type_to_resolve.respond_to?(:raw_type)
|
|
135
|
+
type_to_resolve.raw_type
|
|
136
|
+
elsif type_to_resolve.is_a?(T::Types::TypedArray)
|
|
137
|
+
Array
|
|
138
|
+
elsif type_to_resolve.is_a?(EasyTalk::Types::Tuple)
|
|
139
|
+
Array
|
|
140
|
+
elsif type_to_resolve.is_a?(Symbol) || type_to_resolve.is_a?(String)
|
|
141
|
+
begin
|
|
142
|
+
type_to_resolve.to_s.classify.constantize
|
|
143
|
+
rescue StandardError
|
|
144
|
+
String
|
|
145
|
+
end
|
|
146
|
+
elsif TypeIntrospection.boolean_type?(type_to_resolve)
|
|
147
|
+
[TrueClass, FalseClass]
|
|
148
|
+
elsif nilable_type?(type_to_resolve)
|
|
149
|
+
extract_inner_type(type_to_resolve)
|
|
150
|
+
else
|
|
151
|
+
String
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EasyTalk
|
|
4
|
+
module ValidationAdapters
|
|
5
|
+
# No-op validation adapter.
|
|
6
|
+
#
|
|
7
|
+
# This adapter does not apply any validations. Use it when you want
|
|
8
|
+
# schema generation without any validation side effects.
|
|
9
|
+
#
|
|
10
|
+
# @example Disabling validations for a model
|
|
11
|
+
# class ApiContract
|
|
12
|
+
# include EasyTalk::Model
|
|
13
|
+
#
|
|
14
|
+
# define_schema(validations: :none) do
|
|
15
|
+
# property :name, String, min_length: 5
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# contract = ApiContract.new(name: 'X')
|
|
20
|
+
# contract.valid? # => true (no validations applied)
|
|
21
|
+
#
|
|
22
|
+
# @example Using globally
|
|
23
|
+
# EasyTalk.configure do |config|
|
|
24
|
+
# config.validation_adapter = :none
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
class NoneAdapter < Base
|
|
28
|
+
# Build no schema-level validations (no-op).
|
|
29
|
+
#
|
|
30
|
+
# @param klass [Class] The model class (unused)
|
|
31
|
+
# @param schema [Hash] The schema hash (unused)
|
|
32
|
+
# @return [void]
|
|
33
|
+
def self.build_schema_validations(klass, schema)
|
|
34
|
+
# Intentionally empty - no validations applied
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Apply no validations (no-op).
|
|
38
|
+
#
|
|
39
|
+
# @return [void]
|
|
40
|
+
def apply_validations
|
|
41
|
+
# Intentionally empty - no validations applied
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EasyTalk
|
|
4
|
+
module ValidationAdapters
|
|
5
|
+
# Registry for validation adapters.
|
|
6
|
+
#
|
|
7
|
+
# The registry allows adapters to be registered with symbolic names and
|
|
8
|
+
# resolved from various input types (symbols, classes, or nil for default).
|
|
9
|
+
#
|
|
10
|
+
# @example Registering an adapter
|
|
11
|
+
# EasyTalk::ValidationAdapters::Registry.register(:custom, MyCustomAdapter)
|
|
12
|
+
#
|
|
13
|
+
# @example Resolving an adapter
|
|
14
|
+
# adapter = EasyTalk::ValidationAdapters::Registry.resolve(:active_model)
|
|
15
|
+
# adapter.build_validations(klass, :name, String, {})
|
|
16
|
+
#
|
|
17
|
+
class Registry
|
|
18
|
+
class << self
|
|
19
|
+
# Get the hash of registered adapters.
|
|
20
|
+
#
|
|
21
|
+
# @return [Hash{Symbol => Class}] The registered adapters
|
|
22
|
+
def adapters
|
|
23
|
+
@adapters ||= {}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Register an adapter with a symbolic name.
|
|
27
|
+
#
|
|
28
|
+
# @param name [Symbol, String] The adapter identifier
|
|
29
|
+
# @param adapter_class [Class] The adapter class (must respond to .build_validations)
|
|
30
|
+
# @raise [ArgumentError] if the adapter does not respond to .build_validations
|
|
31
|
+
# @return [void]
|
|
32
|
+
def register(name, adapter_class)
|
|
33
|
+
raise ArgumentError, "Adapter must respond to .build_validations" unless adapter_class.respond_to?(:build_validations)
|
|
34
|
+
|
|
35
|
+
adapters[name.to_sym] = adapter_class
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Resolve an adapter from various input types.
|
|
39
|
+
#
|
|
40
|
+
# @param adapter [Symbol, Class, nil] The adapter identifier or class
|
|
41
|
+
# - nil: returns the default :active_model adapter
|
|
42
|
+
# - Symbol: looks up the adapter by name in the registry
|
|
43
|
+
# - Class: returns the class directly (assumes it implements the adapter interface)
|
|
44
|
+
# @return [Class] The adapter class
|
|
45
|
+
# @raise [ArgumentError] if the adapter symbol is not registered or type is invalid
|
|
46
|
+
def resolve(adapter)
|
|
47
|
+
case adapter
|
|
48
|
+
when nil
|
|
49
|
+
adapters[:active_model] || raise(ArgumentError, "No default adapter registered")
|
|
50
|
+
when Symbol
|
|
51
|
+
adapters[adapter] || raise(ArgumentError, "Unknown validation adapter: #{adapter.inspect}")
|
|
52
|
+
when Class
|
|
53
|
+
adapter
|
|
54
|
+
else
|
|
55
|
+
raise ArgumentError, "Invalid adapter type: #{adapter.class}. Expected Symbol, Class, or nil."
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Check if an adapter is registered with the given name.
|
|
60
|
+
#
|
|
61
|
+
# @param name [Symbol, String] The adapter name to check
|
|
62
|
+
# @return [Boolean] true if the adapter is registered
|
|
63
|
+
def registered?(name)
|
|
64
|
+
adapters.key?(name.to_sym)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Reset the registry (useful for testing).
|
|
68
|
+
# Re-registers the default adapters after clearing.
|
|
69
|
+
#
|
|
70
|
+
# @return [void]
|
|
71
|
+
def reset!
|
|
72
|
+
@adapters = nil
|
|
73
|
+
register_default_adapters
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Register the default validation adapters.
|
|
77
|
+
# This is called during gem initialization and after reset!
|
|
78
|
+
#
|
|
79
|
+
# @return [void]
|
|
80
|
+
def register_default_adapters
|
|
81
|
+
register(:active_model, ActiveModelAdapter)
|
|
82
|
+
register(:none, NoneAdapter)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|