Class: Foobara::Types::Type

Inherits:
Value::Processor::Pipeline show all
Includes:
IsManifestable, Concerns::Reflection, Concerns::SupportedProcessorRegistration
Defined in:
foobara-0.2.2/projects/types/src/type.rb,
foobara-0.2.2/projects/types/src/type/concerns/reflection.rb,
foobara-0.2.2/projects/types/src/type/concerns/supported_processor_registration.rb

Overview

TODO: move casting interface to here?

Direct Known Subclasses

DetachedEntityType

Defined Under Namespace

Modules: Concerns

Instance Attribute Summary collapse

Attributes inherited from Value::Processor::Multi

#prioritize

Attributes inherited from Value::Processor

#created_in_namespace, #declaration_data, #parent_declaration_data

Class Method Summary collapse

Instance Method Summary collapse

Methods included from IsManifestable

#foobara_domain, #foobara_organization, #scoped_clear_caches

Methods included from Concerns::Reflection

#deep_types_depended_on, #inspect, #type_at_path, #types_depended_on, #types_to_add_to_manifest

Methods included from Concern

foobara_class_methods_module_for, foobara_concern?, included

Methods included from Concerns::SupportedProcessorRegistration

#all_supported_processor_classes, #find_supported_processor_class, #register_supported_processor_class, #supported_processor_classes

Methods inherited from Value::Processor::Pipeline

foobara_manifest, #process_outcome, #process_value

Methods inherited from Value::Processor::Multi

#error_classes, #possible_errors, #processor_names, #register

Methods inherited from Value::Processor

#always_applicable?, #attribute_name, #build_error, default_declaration_data, #dup_processor, error_class, error_classes, #error_context, #error_message, #error_path, foobara_manifest, #inspect, instance, #method_missing, new_with_agnostic_args, #possible_errors, #priority, #process_outcome, #process_outcome!, #process_value, #process_value!, processor_name, requires_parent_declaration_data?, #respond_to_missing?, #runner, symbol

Constructor Details

#initialize(declaration_data, target_classes:, base_type:, description: nil, name: "anonymous", casters: [], transformers: [], validators: [], element_processors: nil, structure_count: nil, processor_classes_requiring_type: nil, sensitive: nil, sensitive_exposed: nil, **opts) ⇒ Type

Returns a new instance of Type.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'foobara-0.2.2/projects/types/src/type.rb', line 39

def initialize(
  declaration_data,
  target_classes:,
  base_type:,
  description: nil,
  name: "anonymous",
  casters: [],
  transformers: [],
  validators: [],
  element_processors: nil,
  structure_count: nil,
  processor_classes_requiring_type: nil,
  sensitive: nil,
  sensitive_exposed: nil,
  **opts
)
  self.declaration_data = declaration_data
  self.sensitive = sensitive
  self.sensitive_exposed = sensitive_exposed
  self.base_type = base_type
  self.description = description
  self.name = name
  self.casters = [*casters, *base_type&.casters]
  self.transformers = [*transformers, *base_type&.transformers]
  self.validators = [*validators, *base_type&.validators]
  self.element_processors = [*element_processors, *base_type&.element_processors]

  self.structure_count = structure_count
  self.target_classes = Util.array(target_classes)
  self.processor_classes_requiring_type = processor_classes_requiring_type

  super(declaration_data, **opts.merge(processors:, prioritize: false))

  apply_all_processors_needing_type!

  validate_processors!
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Foobara::Value::Processor

Instance Attribute Details

#base_typeObject

Returns the value of attribute base_type.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def base_type
  @base_type
end

#cast_even_if_instance_of_target_typeObject

Returns the value of attribute cast_even_if_instance_of_target_type.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def cast_even_if_instance_of_target_type
  @cast_even_if_instance_of_target_type
end

#castersObject

Returns the value of attribute casters.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def casters
  @casters
end

#descriptionObject

Returns the value of attribute description.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def description
  @description
end

#element_processorsObject

Returns the value of attribute element_processors.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def element_processors
  @element_processors
end

#element_typeObject



94
95
96
97
98
99
100
101
102
# File 'foobara-0.2.2/projects/types/src/type.rb', line 94

def element_type
  lru_cache.cached([self, :element_type]) do
    if element_type_loader
      element_type_loader.resolve(self)
    else
      base_type&.element_type
    end
  end
end

#element_type_loaderObject

Returns the value of attribute element_type_loader.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def element_type_loader
  @element_type_loader
end

#element_typesObject



104
105
106
107
108
109
110
111
112
# File 'foobara-0.2.2/projects/types/src/type.rb', line 104

def element_types
  lru_cache.cached([self, :element_types]) do
    if element_types_loader
      element_types_loader.resolve(self)
    else
      base_type&.element_types
    end
  end
end

#element_types_loaderObject

Returns the value of attribute element_types_loader.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def element_types_loader
  @element_types_loader
end

#is_builtinObject

Returns the value of attribute is_builtin.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def is_builtin
  @is_builtin
end

#nameObject

Returns the value of attribute name.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def name
  @name
end

#processor_classes_requiring_typeObject

Returns the value of attribute processor_classes_requiring_type.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def processor_classes_requiring_type
  @processor_classes_requiring_type
end

#sensitiveObject

Returns the value of attribute sensitive.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def sensitive
  @sensitive
end

#sensitive_exposedObject

Returns the value of attribute sensitive_exposed.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def sensitive_exposed
  @sensitive_exposed
end

#structure_countObject

Returns the value of attribute structure_count.



17
18
19
# File 'foobara-0.2.2/projects/types/src/type.rb', line 17

def structure_count
  @structure_count
end

#target_classesObject

Returns the value of attribute target_classes.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def target_classes
  @target_classes
end

#transformersObject

Returns the value of attribute transformers.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def transformers
  @transformers
end

#type_symbolObject

Returns the value of attribute type_symbol.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def type_symbol
  @type_symbol
end

#validatorsObject

Returns the value of attribute validators.



27
28
29
# File 'foobara-0.2.2/projects/types/src/type.rb', line 27

def validators
  @validators
end

Class Method Details

.requires_declaration_data?Boolean

Returns:

  • (Boolean)


12
13
14
# File 'foobara-0.2.2/projects/types/src/type.rb', line 12

def requires_declaration_data?
  true
end

Instance Method Details

#applicable?(value) ⇒ Boolean

Returns:

  • (Boolean)


415
416
417
# File 'foobara-0.2.2/projects/types/src/type.rb', line 415

def applicable?(value)
  !value_caster.needs_cast?(value) || value_caster.can_cast?(value)
end

#apply_all_processors_needing_type!Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'foobara-0.2.2/projects/types/src/type.rb', line 138

def apply_all_processors_needing_type!
  each_processor_class_requiring_type do |processor_class|
    # TODO: is this a smell?
    processor = processor_class.new(self)

    category = case processor
               when Value::Caster
                 casters
               when Value::Validator
                 # :nocov:
                 validators
                 # :nocov:
               when Value::Transformer
                 # :nocov:
                 transformers
                 # :nocov:
               when Types::ElementProcessor
                 # :nocov:
                 element_processors
                 # :nocov:
               else
                 # TODO: add validator that these are all fine so we don't have to bother here...
                 # :nocov:
                 raise "Not sure where to put #{processor}"
                 # :nocov:
               end

    symbol = processor.symbol
    category.delete_if { |p| p.symbol == symbol }

    category << processor
    clear_caches
  end
end

#base_type_for_manifestObject



567
568
569
# File 'foobara-0.2.2/projects/types/src/type.rb', line 567

def base_type_for_manifest
  base_type
end

#builtin?Boolean

TODO: replace the concept of builtin? with primitive? and delete this method since primitive? already exists.

Returns:

  • (Boolean)


563
564
565
# File 'foobara-0.2.2/projects/types/src/type.rb', line 563

def builtin?
  is_builtin
end

#cast(value) ⇒ Object



421
422
423
# File 'foobara-0.2.2/projects/types/src/type.rb', line 421

def cast(value)
  value_caster.process_value(value)
end

#cast!(value) ⇒ Object



425
426
427
# File 'foobara-0.2.2/projects/types/src/type.rb', line 425

def cast!(value)
  value_caster.process_value!(value)
end

#clear_cachesObject



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'foobara-0.2.2/projects/types/src/type.rb', line 173

def clear_caches
  [
    :@value_validator,
    :@processors,
    :@value_caster,
    :@value_transformer,
    :@element_processor,
    :@possible_errors,
    :@processors_without_casters
  ].each do |instance_variable|
    if instance_variable_defined?(instance_variable)
      remove_instance_variable(instance_variable)
    end
  end
end

#derived?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'foobara-0.2.2/projects/types/src/type.rb', line 82

def derived?
  declaration_data.is_a?(::Hash)
end

#each_processor_class_requiring_type(&block) ⇒ Object



213
214
215
216
217
218
219
# File 'foobara-0.2.2/projects/types/src/type.rb', line 213

def each_processor_class_requiring_type(&block)
  base_type&.each_processor_class_requiring_type(&block)

  processor_classes_requiring_type&.each do |processor_class|
    block.call(processor_class)
  end
end

#element_processorObject



452
453
454
455
456
457
458
# File 'foobara-0.2.2/projects/types/src/type.rb', line 452

def element_processor
  return @element_processor if defined?(@element_processor)

  @element_processor = if element_processors && !element_processors.empty?
                         Value::Processor::Pipeline.new(processors: element_processors)
                       end
end

#extends?(type) ⇒ Boolean

Returns:

  • (Boolean)


267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'foobara-0.2.2/projects/types/src/type.rb', line 267

def extends?(type)
  case type
  when Type
    extends_type?(type)
  when Symbol, String
    concrete_type = created_in_namespace.foobara_lookup_type(type)
    if concrete_type.nil?
      # :nocov:
      raise "No type found for #{type}"
      # :nocov:
    end

    extends_type?(concrete_type)
  else
    # :nocov:
    raise ArgumentError, "Expected a Type or a Symbol/String, but got #{type.inspect}"
    # :nocov:
  end
end

#extends_directly?(type) ⇒ Boolean

Returns:

  • (Boolean)


287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'foobara-0.2.2/projects/types/src/type.rb', line 287

def extends_directly?(type)
  case type
  when Type
    base_type == type
  when Symbol, String
    concrete_type = created_in_namespace.foobara_lookup_type(type)

    if concrete_type.nil?
      # :nocov:
      raise "No type found for #{type}"
      # :nocov:
    end

    extends_directly?(concrete_type)
  else
    # :nocov:
    raise ArgumentError, "Expected a Type or a Symbol/String, but got #{type.inspect}"
    # :nocov:
  end
end

#extends_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'foobara-0.2.2/projects/types/src/type.rb', line 308

def extends_type?(type)
  return true if self == type

  unless type
    # :nocov:
    raise ArgumentError, "Expected a type but got nil"
    # :nocov:
  end

  if registered?
    if type.registered?
      if type.foobara_manifest_reference == foobara_manifest_reference
        return true
      end
    end
  end

  base_type&.extends_type?(type)
end

#foobara_manifestObject



501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'foobara-0.2.2/projects/types/src/type.rb', line 501

def foobara_manifest
  to_include = TypeDeclarations.foobara_manifest_context_to_include
  remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
  include_processors = TypeDeclarations.include_processors?

  types = []

  types_depended_on.each do |dependent_type|
    if dependent_type.registered?
      types << dependent_type.foobara_manifest_reference
      if to_include
        to_include << dependent_type
      end
    end
  end

  possible_errors_manifests = possible_errors.map do |possible_error|
    [possible_error.key.to_s, possible_error.foobara_manifest]
  end.sort.to_h

  declaration_data = self.declaration_data

  if remove_sensitive
    declaration_data = TypeDeclarations.remove_sensitive_types(declaration_data)
  end

  h = Util.remove_blank(
    name:,
    target_classes: target_classes.map(&:name).sort,
    declaration_data:,
    types_depended_on: types.sort,
    possible_errors: possible_errors_manifests,
    builtin: builtin?
  ).merge(description:, base_type: base_type_for_manifest&.full_type_name&.to_sym)

  if sensitive?
    h[:sensitive] = true
  end

  if sensitive_exposed?
    h[:sensitive_exposed] = true
  end

  if include_processors
    h.merge!(
      supported_processor_manifest.merge(
        Util.remove_blank(processors: processor_manifest)
      )
    )
  end

  target_classes.sort_by(&:name).each do |target_class|
    if target_class.respond_to?(:foobara_manifest)
      h.merge!(target_class.foobara_manifest)
    end
  end

  super.merge(h)
end

#foobara_manifest_referenceObject

TODO: put this somewhere else



497
498
499
# File 'foobara-0.2.2/projects/types/src/type.rb', line 497

def foobara_manifest_reference
  scoped_full_name
end

#full_type_nameObject



475
476
477
# File 'foobara-0.2.2/projects/types/src/type.rb', line 475

def full_type_name
  scoped_full_name
end

#full_type_symbolObject



374
375
376
377
378
379
380
# File 'foobara-0.2.2/projects/types/src/type.rb', line 374

def full_type_symbol
  return @full_type_symbol if defined?(@full_type_symbol)

  @full_type_symbol ||= if scoped_path_set?
                          scoped_full_name.to_sym
                        end
end

#has_sensitive_types?Boolean

Returns:

  • (Boolean)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'foobara-0.2.2/projects/types/src/type.rb', line 114

def has_sensitive_types?
  return true if sensitive?

  # TODO: this is a hack... come up with a better/separate way to detect types with private attributes
  if declaration_data.is_a?(::Hash)
    private = declaration_data[:private]
    return true if private.is_a?(::Array) && !private.empty?
  end

  if element_type
    return true if element_type.has_sensitive_types?
  end

  if element_types
    types = if element_types.is_a?(::Hash)
              element_types.values
            else
              [*element_types]
            end

    types.any?(&:has_sensitive_types?)
  end
end

#primitive?Boolean

TODO: replace the concept of builtin? with primitive?

Returns:

  • (Boolean)


78
79
80
# File 'foobara-0.2.2/projects/types/src/type.rb', line 78

def primitive?
  declaration_data.is_a?(::Symbol)
end

#processor_manifestObject



605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
# File 'foobara-0.2.2/projects/types/src/type.rb', line 605

def processor_manifest
  to_include = TypeDeclarations.foobara_manifest_context_to_include

  casters_manifest = []
  transformers_manifest = []
  validators_manifest = []
  caster_classes_manifest = []
  transformer_classes_manifest = []
  validator_classes_manifest = []

  casters.each do |caster|
    klass = caster.class
    if to_include
      to_include << klass
    end
    caster_classes_manifest << klass.foobara_manifest_reference

    if caster.scoped_path_set?
      if to_include
        to_include << caster
      end
      casters_manifest << caster.foobara_manifest_reference
    end
  end

  transformers.each do |transformer|
    klass = transformer.class
    if to_include
      to_include << klass
    end
    transformer_classes_manifest << klass.foobara_manifest_reference

    if transformer.scoped_path_set?
      if to_include
        to_include << transformer
      end
      transformers_manifest << transformer.foobara_manifest_reference
    end
  end

  validators.each do |validator|
    klass = validator.class
    if to_include
      to_include << klass
    end
    validator_classes_manifest << klass.foobara_manifest_reference

    if validator.scoped_path_set?
      if to_include
        to_include << validator
      end
      validators_manifest << validator.foobara_manifest_reference
    end
  end

  Util.remove_blank(
    casters: casters_manifest.sort,
    caster_classes: caster_classes_manifest.sort,
    transformers: transformers_manifest.sort,
    transformer_classes: transformer_classes_manifest.sort,
    validators: validators_manifest.sort,
    validator_classes: validator_classes_manifest.sort
  )
end

#processorsObject



382
383
384
385
386
387
388
389
# File 'foobara-0.2.2/projects/types/src/type.rb', line 382

def processors
  @processors ||= [
    value_caster,
    value_transformer,
    value_validator,
    element_processor
  ].compact.sort_by(&:priority)
end

#processors=Object



328
329
330
331
# File 'foobara-0.2.2/projects/types/src/type.rb', line 328

def processors=(...)
  clear_caches
  super
end

#reference_or_declaration_data(declaration_data = self.declaration_data) ⇒ Object



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
# File 'foobara-0.2.2/projects/types/src/type.rb', line 479

def reference_or_declaration_data(declaration_data = self.declaration_data)
  remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?

  if registered?
    # TODO: we should just use the symbol and nothing else in this context instead of a hash with 1 element.
    if scoped_unregistered?
      unregistered_foobara_manifest_reference.to_sym
    else
      foobara_manifest_reference.to_sym
    end
  elsif remove_sensitive
    TypeDeclarations.remove_sensitive_types(declaration_data)
  else
    declaration_data
  end
end

#registered?Boolean

Returns:

  • (Boolean)


670
671
672
# File 'foobara-0.2.2/projects/types/src/type.rb', line 670

def registered?
  !!type_symbol
end

#remove_caster_instances_of(klass) ⇒ Object



189
190
191
192
193
194
195
# File 'foobara-0.2.2/projects/types/src/type.rb', line 189

def remove_caster_instances_of(klass)
  self.casters = casters.reject do |caster|
    caster.is_a?(klass)
  end

  clear_caches
end

#remove_processor_by_symbol(symbol) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'foobara-0.2.2/projects/types/src/type.rb', line 197

def remove_processor_by_symbol(symbol)
  [
    casters,
    element_processors,
    processor_classes_requiring_type,
    processors,
    transformers,
    validators
  ].each do |processor_collection|
    processor_collection&.delete_if { |p| p.symbol == symbol }
  end
  supported_processor_classes&.each { |processor_hash| processor_hash.delete(symbol) }
  processor_classes_requiring_type&.delete_if { |p| p.symbol == symbol }
  clear_caches
end

#sensitive?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'foobara-0.2.2/projects/types/src/type.rb', line 86

def sensitive?
  sensitive
end

#sensitive_exposed?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'foobara-0.2.2/projects/types/src/type.rb', line 90

def sensitive_exposed?
  sensitive_exposed
end

#supported_processor_manifestObject



571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
# File 'foobara-0.2.2/projects/types/src/type.rb', line 571

def supported_processor_manifest
  to_include = TypeDeclarations.foobara_manifest_context_to_include

  supported_casters = []
  supported_transformers = []
  supported_validators = []
  supported_processors = []

  all_supported_processor_classes.each do |processor_class|
    if to_include
      to_include << processor_class
    end

    target = if processor_class < Value::Caster
               supported_casters
             elsif processor_class < Value::Validator
               supported_validators
             elsif processor_class < Value::Transformer
               supported_transformers
             else
               supported_processors
             end

    target << processor_class.foobara_manifest_reference
  end

  Util.remove_blank(
    supported_casters: supported_casters.sort,
    supported_transformers: supported_transformers.sort,
    supported_validators: supported_validators.sort,
    supported_processors: supported_processors.sort
  )
end

#target_classObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'foobara-0.2.2/projects/types/src/type.rb', line 249

def target_class
  if target_classes.empty?
    # :nocov:
    # TODO: We really need a better error message when we hit this point in the code path.
    # One thing that can cause this is if you create a custom type called :model but it isn't loaded
    # yet and we accidentally are referring to the builtin :model type.  This error message doesn't reveal
    # that you need to require the custom :model.
    raise "No target classes"
    # :nocov:
  elsif target_classes.size > 1
    # :nocov:
    raise "Cannot use #target_class because this type has multiple target_classes"
    # :nocov:
  end

  target_classes.first
end

#validate_processors!Object



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'foobara-0.2.2/projects/types/src/type.rb', line 221

def validate_processors!
  all = [casters, transformers, validators, element_processors]

  all.each do |processor_group|
    processor_group.each.with_index do |processor, index|
      if processor.requires_parent_declaration_data?
        processor_group[index] = processor.dup_processor(parent_declaration_data: declaration_data)
      end
    end

    processor_group.group_by(&:symbol).each_pair do |symbol, members|
      if members.size > 1
        if members.map { |m| m.class.name }.uniq.size == members.size
          members[1..].each do |member|
            processor_group.delete(member)
          end
        else
          # :nocov:
          raise "Type #{name} has multiple processors with symbol #{symbol}"
          # :nocov:
        end
      end
    end
  end

  clear_caches
end

#validation_errors(value) ⇒ Object

TODO: some way of memoizing these values? Would need to introduce a new class that takes the value to its constructor



462
463
464
465
466
467
468
469
470
471
472
473
# File 'foobara-0.2.2/projects/types/src/type.rb', line 462

def validation_errors(value)
  value = cast!(value)
  if value_transformer
    value = value_transformer.process_value!(value)
  end

  if value_validator
    value_validator.process_value(value).errors
  else
    []
  end
end

#value_casterObject



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'foobara-0.2.2/projects/types/src/type.rb', line 391

def value_caster
  return @value_caster if defined?(@value_caster)

  # We make this exception for :duck because it will match any instance of
  # Object but AllowNil will match nil which is also an instance of Object.
  # This results in two matching casters. Instead of figuring out a way to make one
  # conditional on the other we will just turn off this unique enforcement for :duck
  enforce_unique = if declaration_data.is_a?(::Hash)
                     declaration_data[:type] != :duck
                   else
                     true
                   end

  Namespace.use created_in_namespace do
    @value_caster = Value::Processor::Casting.new(
      { cast_to: reference_or_declaration_data },
      casters:,
      target_classes:,
      enforce_unique:,
      cast_even_if_instance_of_target_type:
    )
  end
end

#value_transformerObject

TODO: an interesting thought… we have Processor and then a subclass of Processor and then an instance of processor that encapsulates the declaration_data for that processor. But then we pass ‘value` to every method in the instance of the processor as needed. This means it can’t really memoize stuff. Should we create an instance of something from the instance of the processor and then ask it questions?? TODO: try this



433
434
435
436
437
438
439
# File 'foobara-0.2.2/projects/types/src/type.rb', line 433

def value_transformer
  return @value_transformer if defined?(@value_transformer)

  @value_transformer = if transformers && !transformers.empty?
                         Value::Processor::Pipeline.new(processors: transformers)
                       end
end

#value_validatorObject

TODO: figure out how to safely memoize stuff so like this for performance reasons A good way, but potentially a decent amount of work, is to have a class that takes value to its initialize method.



444
445
446
447
448
449
450
# File 'foobara-0.2.2/projects/types/src/type.rb', line 444

def value_validator
  return @value_validator if defined?(@value_validator)

  @value_validator = if validators && !validators.empty?
                       Value::Processor::Pipeline.new(processors: validators)
                     end
end