Class: Parametric::Field
- Inherits:
-
Object
- Object
- Parametric::Field
- Includes:
- FieldDSL
- Defined in:
- lib/parametric/field.rb
Defined Under Namespace
Classes: PolicyWithKey, Result
Instance Attribute Summary collapse
-
#key ⇒ Object
readonly
Returns the value of attribute key.
-
#meta_data ⇒ Object
readonly
Returns the value of attribute meta_data.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #default(value) ⇒ Object
- #from(another_field) ⇒ Object
- #has_policy?(key) ⇒ Boolean
-
#initialize(key, registry = Parametric.registry) ⇒ Field
constructor
A new instance of Field.
- #meta(hash = nil) ⇒ Object
-
#one_of(*schemas) ⇒ Field
Validate field value against multiple schemas, accepting the first valid match.
- #policy(key, *args) ⇒ Object (also: #type)
- #resolve(payload, context) ⇒ Object
- #schema(sc = nil, &block) ⇒ Object
- #tagged_one_of(instance = nil, &block) ⇒ Object
- #visit(meta_key = nil, &visitor) ⇒ Object
-
#wrap(wrapper) ⇒ Field
Wraps a field with a custom type that handles both coercion and validation.
Methods included from FieldDSL
#declared, #nullable, #options, #present, #required
Constructor Details
#initialize(key, registry = Parametric.registry) ⇒ Field
Returns a new instance of Field.
19 20 21 22 23 24 25 26 |
# File 'lib/parametric/field.rb', line 19 def initialize(key, registry = Parametric.registry) @key = key @policies = [] @registry = registry @default_block = nil @meta_data = {} @policies = [] end |
Instance Attribute Details
#key ⇒ Object (readonly)
Returns the value of attribute key.
16 17 18 |
# File 'lib/parametric/field.rb', line 16 def key @key end |
#meta_data ⇒ Object (readonly)
Returns the value of attribute meta_data.
16 17 18 |
# File 'lib/parametric/field.rb', line 16 def @meta_data end |
Instance Method Details
#==(other) ⇒ Object
28 29 30 |
# File 'lib/parametric/field.rb', line 28 def ==(other) other.is_a?(Field) && key == other.key && policies == other.policies && == other. end |
#default(value) ⇒ Object
37 38 39 40 41 |
# File 'lib/parametric/field.rb', line 37 def default(value) default: value @default_block = (value.respond_to?(:call) ? value : ->(key, payload, context) { value }) self end |
#from(another_field) ⇒ Object
149 150 151 152 153 154 155 156 |
# File 'lib/parametric/field.rb', line 149 def from(another_field) another_field. another_field.policies.each do |plc| policies << plc end self end |
#has_policy?(key) ⇒ Boolean
158 159 160 |
# File 'lib/parametric/field.rb', line 158 def has_policy?(key) policies.any? { |pol| pol.key == key } end |
#meta(hash = nil) ⇒ Object
32 33 34 35 |
# File 'lib/parametric/field.rb', line 32 def (hash = nil) @meta_data = @meta_data.merge(hash) if hash.is_a?(Hash) self end |
#one_of(*schemas) ⇒ Field
Validate field value against multiple schemas, accepting the first valid match.
This method allows a field to accept one of several possible object structures. It validates the input against each provided schema in order and uses the output from the first schema that successfully validates the input.
The validation fails if:
-
No schemas match the input (invalid data)
-
Multiple schemas match the input (ambiguous structure)
89 90 91 |
# File 'lib/parametric/field.rb', line 89 def one_of(*schemas) policy OneOf.new(schemas) end |
#policy(key, *args) ⇒ Object Also known as: type
43 44 45 46 47 48 |
# File 'lib/parametric/field.rb', line 43 def policy(key, *args) pol = lookup(key, args) pol. policies << pol self end |
#resolve(payload, context) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/parametric/field.rb', line 175 def resolve(payload, context) eligible = payload.key?(key) value = payload[key] # might be nil if !eligible && has_default? eligible = true value = default_block.call(key, payload, context) return Result.new(eligible, value) end policies.each do |policy| begin pol = policy.build(key, value, payload:, context:) if !pol.eligible? eligible = pol.include_non_eligible_in_ouput? if has_default? eligible = true value = default_block.call(key, payload, context) end break else value = pol.value if !pol.valid? eligible = true # eligible, but has errors context.add_error pol. break # only one error at a time end end rescue StandardError => e context.add_error e. break end end Result.new(eligible, value) end |
#schema(sc = nil, &block) ⇒ Object
143 144 145 146 147 |
# File 'lib/parametric/field.rb', line 143 def schema(sc = nil, &block) sc = (sc ? sc : Schema.new(&block)) schema: sc policy sc.schema end |
#tagged_one_of(instance = nil, &block) ⇒ Object
51 52 53 |
# File 'lib/parametric/field.rb', line 51 def tagged_one_of(instance = nil, &block) policy(instance || Parametric::TaggedOneOf.new(&block)) end |
#visit(meta_key = nil, &visitor) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/parametric/field.rb', line 162 def visit( = nil, &visitor) if sc = [:schema] if sc.is_a?(Array) sc.map { |s| s.schema.visit(, &visitor) } else r = sc.schema.visit(, &visitor) ([:type] == :array) ? [r] : r end else ? [] : yield(self) end end |
#wrap(wrapper) ⇒ Field
Wraps a field with a custom type that handles both coercion and validation.
The wrapper object must implement two methods:
-
‘coerce(value)`: Converts the input value to the desired type
-
‘errors`: Returns a hash of validation errors (empty hash if valid)
This is useful for integrating domain objects, value objects, or custom types that have their own validation logic into Parametric schemas.
139 140 141 |
# File 'lib/parametric/field.rb', line 139 def wrap(wrapper) policy Wrapper.new(wrapper) end |