Class: Foobara::Value::Processor::Casting

Inherits:
Selection show all
Defined in:
foobara-0.2.2/projects/value/src/processor/casting.rb

Overview

TODO: at least move this up to Types though that doesn’t solve the issue

Defined Under Namespace

Classes: CannotCastError

Instance Attribute Summary collapse

Attributes inherited from Selection

#enforce_unique, #error_if_none_applicable

Attributes inherited from Multi

#prioritize, #processors

Attributes inherited from Foobara::Value::Processor

#created_in_namespace, #declaration_data, #parent_declaration_data

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Selection

#always_applicable?, #process_value!, #processor_for, #processor_for!

Methods inherited from Multi

#applicable?, #error_classes, #possible_errors, #processor_names, #register

Methods inherited from Foobara::Value::Processor

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

Methods included from IsManifestable

#foobara_domain, #foobara_manifest, #foobara_organization, #scoped_clear_caches

Methods included from Concern

foobara_class_methods_module_for, foobara_concern?, included

Constructor Details

#initialize(casters:, target_classes: nil, cast_even_if_instance_of_target_type: nil) ⇒ Casting

Returns a new instance of Casting.



42
43
44
45
46
47
48
49
50
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 42

def initialize(*, casters:, target_classes: nil, cast_even_if_instance_of_target_type: nil, **)
  self.target_classes = Util.array(target_classes)

  if cast_even_if_instance_of_target_type
    self.cast_even_if_instance_of_target_type = true
  end

  super(*, processors: casters, **)
end

Dynamic Method Handling

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

Instance Attribute Details

#cast_even_if_instance_of_target_typeObject

Returns the value of attribute cast_even_if_instance_of_target_type.



40
41
42
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 40

def cast_even_if_instance_of_target_type
  @cast_even_if_instance_of_target_type
end

#target_classesObject

Returns the value of attribute target_classes.



40
41
42
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 40

def target_classes
  @target_classes
end

Class Method Details

.error_classesObject



31
32
33
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 31

def error_classes
  [CannotCastError]
end

.foobara_manifestObject



25
26
27
28
29
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 25

def foobara_manifest
  # :nocov:
  super.merge(processor_type: :casting)
  # :nocov:
end

.requires_declaration_data?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 35

def requires_declaration_data?
  true
end

Instance Method Details

#applies_messageObject



80
81
82
83
84
85
86
87
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 80

def applies_message
  Util.to_or_sentence(
    [
      "be a #{target_classes.map(&:name).join(" or ")}",
      *processors.map(&:applies_message).flatten
    ]
  )
end

#build_error(*args, **opts) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 96

def build_error(*args, **opts)
  error_class = opts[:error_class]

  if error_class == NoApplicableProcessorError
    build_error(*args)
  elsif error_class == MoreThanOneApplicableProcessorError
    # :nocov:
    raise "Matched too many casters for #{args.map(&:inspect).join(",")} with #{opts.inspect}"
    # :nocov:
  else
    super
  end
end

#can_cast?(value) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 64

def can_cast?(value)
  processors.any? { |processor| processor.applicable?(value) }
end

#cast_toObject



110
111
112
113
114
115
116
117
118
119
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 110

def cast_to
  # TODO: isn't there a way to declare declaration_data_type so we don't have to validate here??
  unless declaration_data.key?(:cast_to)
    # :nocov:
    raise "Missing cast_to"
    # :nocov:
  end

  declaration_data[:cast_to]
end

#error_context(value) ⇒ Object



89
90
91
92
93
94
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 89

def error_context(value)
  {
    cast_to:,
    value:
  }
end

#error_message(value) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 68

def error_message(value)
  type = declaration_data[:cast_to]

  if type.is_a?(::Hash)
    type = type[:type]
  end

  article = type.to_s =~ /^[aeiouy]/i ? "an" : "a"

  "Cannot cast #{value.inspect} to #{article} #{type}. Expected it to #{applies_message}"
end

#needs_cast?(value) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 60

def needs_cast?(value)
  target_classes.none? { |klass| value.is_a?(klass) }
end

#process_value(value) ⇒ Object



52
53
54
55
56
57
58
# File 'foobara-0.2.2/projects/value/src/processor/casting.rb', line 52

def process_value(value)
  if cast_even_if_instance_of_target_type || needs_cast?(value)
    super
  else
    Outcome.success(value)
  end
end