Module: CMDx::Util

Extended by:
Util
Included in:
Util
Defined in:
lib/cmdx/util.rb

Overview

Shared helpers for ‘:if` / `:unless` gates, recursive hash merge/dup, and related tree utilities used across tasks, context, and i18n.

Instance Method Summary collapse

Instance Method Details

#deep_dup(value) ⇒ Object

Returns a deep copy of ‘value`. Immutable scalars (`Numeric`, `Symbol`, booleans, `nil`) are returned as-is; `Hash` and `Array` are walked recursively; other objects use `#dup`, falling back to the original when `#dup` raises.

Parameters:

  • value (Object)

Returns:

  • (Object)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/cmdx/util.rb', line 93

def deep_dup(value)
  case value
  when Numeric, Symbol, TrueClass, FalseClass, NilClass
    value
  when Hash
    value.each_with_object({}) { |(k, v), acc| acc[k] = deep_dup(v) }
  when Array
    value.map { |e| deep_dup(e) }
  else
    begin
      value.dup
    rescue StandardError
      value
    end
  end
end

#deep_merge(lhs, rhs) ⇒ Object

Recursively merges two Hash-like trees. When both values at a key are Hashes, they merge recursively; otherwise the right-hand value wins (last-write-wins). When either top-level operand is not a Hash, returns ‘rhs` unchanged — useful when folding unknown YAML roots.

Parameters:

  • lhs (Object)

    left tree (typically a Hash)

  • rhs (Object)

    right tree (typically a Hash)

Returns:

  • (Object)

    merged Hash or ‘rhs` when a Hash-only merge is impossible



80
81
82
83
84
# File 'lib/cmdx/util.rb', line 80

def deep_merge(lhs, rhs)
  return rhs unless lhs.is_a?(Hash) && rhs.is_a?(Hash)

  lhs.merge(rhs) { |_key, l, r| deep_merge(l, r) }
end

#evaluate(condition, receiver, *args) ⇒ Boolean, Object

Evaluates a condition against ‘receiver`, dispatching by type.

Parameters:

  • condition (Boolean, nil, Symbol, Proc, #call)

    ‘:if`/`:unless`-style gate, method name, or callable evaluated against `receiver`

  • receiver (Object)

    object the condition runs against (usually a Task)

  • args (Array<Object>)

    extra arguments forwarded to the condition

Returns:

  • (Boolean, Object)

    truthiness result (Procs ‘instance_exec` on receiver)

Raises:

  • (ArgumentError)

    when the condition is not a supported type



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/cmdx/util.rb', line 17

def evaluate(condition, receiver, *args)
  case condition
  when FalseClass, NilClass
    false
  when TrueClass
    true
  when Symbol
    receiver.send(condition, *args)
  when Proc
    receiver.instance_exec(*args, &condition)
  else
    return condition.call(receiver, *args) if condition.respond_to?(:call)

    raise ArgumentError,
      "condition must be a Symbol, Proc, or respond to #call (got #{condition.class})"
  end
end

#if?(condition, receiver, *args) ⇒ Boolean

Evaluates an ‘:if`-style condition. `nil` is treated as “always true”.

Parameters:

  • condition (Boolean, nil, Symbol, Proc, #call)

    gate to check

  • receiver (Object)

    object the condition runs against

  • args (Array<Object>)

    extra arguments forwarded to the condition

Returns:

  • (Boolean)

    true when ‘condition` is nil or evaluates truthy



41
42
43
44
45
# File 'lib/cmdx/util.rb', line 41

def if?(condition, receiver, *args)
  return true if condition.nil?

  evaluate(condition, receiver, *args)
end

#satisfied?(condition_if, condition_unless, receiver, *args) ⇒ Boolean

Combines ‘:if` and `:unless` gates. Used across the framework to decide whether a conditional feature (callback, retry, validator, etc.) should run.

Parameters:

  • condition_if (Boolean, nil, Symbol, Proc, #call)

    ‘:if` gate

  • condition_unless (Boolean, nil, Symbol, Proc, #call)

    ‘:unless` gate

  • receiver (Object)

    object the conditions run against

  • args (Array<Object>)

    extra arguments forwarded to both conditions

Returns:

  • (Boolean)

    true only when both gates pass



67
68
69
70
# File 'lib/cmdx/util.rb', line 67

def satisfied?(condition_if, condition_unless, receiver, *args)
  if?(condition_if, receiver, *args) &&
    unless?(condition_unless, receiver, *args)
end

#to_error_s(error) ⇒ String

Returns a string representation of ‘error` in the format `[Class] Message`.

Parameters:

  • error (Exception)

Returns:

  • (String)


114
115
116
# File 'lib/cmdx/util.rb', line 114

def to_error_s(error)
  "[#{error.class}] #{error.message}"
end

#unless?(condition, receiver, *args) ⇒ Boolean

Evaluates an ‘:unless`-style condition. `nil` is treated as “always true”.

Parameters:

  • condition (Boolean, nil, Symbol, Proc, #call)

    gate to check

  • receiver (Object)

    object the condition runs against

  • args (Array<Object>)

    extra arguments forwarded to the condition

Returns:

  • (Boolean)

    true when ‘condition` is nil or evaluates falsy



53
54
55
56
57
# File 'lib/cmdx/util.rb', line 53

def unless?(condition, receiver, *args)
  return true if condition.nil?

  !evaluate(condition, receiver, *args)
end