Class: Plumb::AttributeValueMatch

Inherits:
Object
  • Object
show all
Includes:
Composable
Defined in:
lib/plumb/attribute_value_match.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Composable

#&, #/, #>>, #[], #absorb_input, #absorb_output, #accepted_type, #as_node, #build, #check, #children, #defer, #fusable_step?, #fuse_with, #generate, #idempotent?, included, #invalid, #invoke, #match, #not, #output_type, #pipeline, #policy, resolve_operand, #static, #subtype_identity, #to_json_schema, #to_mermaid, #to_plumb_type, #to_s, #transform, #where, #with, wrap, #|

Methods included from Callable

#parse, #resolve

Constructor Details

#initialize(type, attr_name, value) ⇒ AttributeValueMatch

Returns a new instance of AttributeValueMatch.



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/plumb/attribute_value_match.rb', line 9

def initialize(type, attr_name, value)
  unless attr_name.is_a?(::Symbol) || attr_name.is_a?(::String)
    raise ArgumentError, "attribute name must be a Symbol or String, got #{attr_name.inspect}"
  end

  @type = type
  @attr_name = attr_name
  @value = value
  @error = "must have attribute #{attr_name} === #{value.inspect}"
  @inspect_line = %((#{attr_name} === #{value.inspect}))
  freeze
end

Instance Attribute Details

#attr_nameObject (readonly)

Returns the value of attribute attr_name.



7
8
9
# File 'lib/plumb/attribute_value_match.rb', line 7

def attr_name
  @attr_name
end

#typeObject (readonly)

Returns the value of attribute type.



7
8
9
# File 'lib/plumb/attribute_value_match.rb', line 7

def type
  @type
end

#valueObject (readonly)

Returns the value of attribute value.



7
8
9
# File 'lib/plumb/attribute_value_match.rb', line 7

def value
  @value
end

Instance Method Details

#==(other) ⇒ Object

Two attribute constraints are equal when they constrain the same attribute of the same base type to the same value. (The default Composable#== only compares #children, which an AttributeValueMatch doesn't expose, so it would treat every constraint as equal.)



26
27
28
29
30
31
# File 'lib/plumb/attribute_value_match.rb', line 26

def ==(other)
  other.is_a?(self.class) &&
    attr_name == other.attr_name &&
    value == other.value &&
    type == other.type
end

#call(result) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/plumb/attribute_value_match.rb', line 58

def call(result)
  # Missing attributes fail the constraint instead of raising.
  return result.invalid!(errors: @error) unless result.value.respond_to?(attr_name)
  return result if value === result.value.public_send(attr_name)

  result.invalid!(errors: @error)
end

#input_typeObject

An attribute-value constraint narrows by value, so it accepts any input (opts out of #>> composition type-checks).



37
# File 'lib/plumb/attribute_value_match.rb', line 37

def input_type = Types::Any

#metadataObject



33
# File 'lib/plumb/attribute_value_match.rb', line 33

def  = type.

#subtype_of?(other) ⇒ Boolean

Subtyping for an attribute constraint. Against another constraint on the SAME attribute, the base types must be compatible and this constraint's value must be a subtype of the other's — eg. size: 10 <= size: 8..100, but size: 10..15 </= size: 11..14. Against any other type, an attribute-constrained type is simply a subtype of its base type (eg. Array.where(size: 10) <= Array).

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
56
# File 'lib/plumb/attribute_value_match.rb', line 48

def subtype_of?(other)
  if other.is_a?(AttributeValueMatch)
    attr_name == other.attr_name &&
      Plumb::Subtyping.subtype?(type, other.type) &&
      Plumb::Subtyping.value_subtype?(value, other.value)
  else
    Plumb::Subtyping.subtype?(type, other)
  end
end

#value_preserving?Boolean

It checks an attribute and returns the value unchanged — a pure refinement.

Returns:

  • (Boolean)


40
# File 'lib/plumb/attribute_value_match.rb', line 40

def value_preserving? = true