Module: StateMachines::OptionsValidator

Defined in:
lib/state_machines/options_validator.rb

Overview

Define the module if it doesn’t exist yet Module for validating options without monkey-patching Hash Provides the same functionality as the Hash monkey patch but in a cleaner way

Class Method Summary collapse

Class Method Details

.assert_exclusive_keys!(options, *exclusive_keys, caller_info: nil) ⇒ Object

Validates that at most one of the exclusive keys is present in the options hash

Parameters:

  • options (Hash)

    The options hash to validate

  • exclusive_keys (Array<Symbol>)

    List of mutually exclusive keys

  • caller_info (String) (defaults to: nil)

    Information about the calling method for better error messages

Raises:

  • (ArgumentError)

    If more than one exclusive key is found



33
34
35
36
37
38
39
40
41
# File 'lib/state_machines/options_validator.rb', line 33

def assert_exclusive_keys!(options, *exclusive_keys, caller_info: nil)
  return if options.empty?

  conflicting_keys = exclusive_keys & options.keys
  return if conflicting_keys.length <= 1

  caller_context = caller_info ? " in #{caller_info}" : ''
  raise ArgumentError, "Conflicting keys: #{conflicting_keys.join(', ')}#{caller_context}"
end

.assert_valid_keys!(options, *valid_keys, caller_info: nil) ⇒ Object

Validates that all keys in the options hash are in the list of valid keys

Parameters:

  • options (Hash)

    The options hash to validate

  • valid_keys (Array<Symbol>)

    List of valid key names

  • caller_info (String) (defaults to: nil)

    Information about the calling method for better error messages

Raises:

  • (ArgumentError)

    If any invalid keys are found



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/state_machines/options_validator.rb', line 15

def assert_valid_keys!(options, *valid_keys, caller_info: nil)
  return if options.empty?

  valid_keys.flatten!
  invalid_keys = options.keys - valid_keys

  return if invalid_keys.empty?

  caller_context = caller_info ? " in #{caller_info}" : ''
  raise ArgumentError, "Unknown key#{'s' if invalid_keys.length > 1}: #{invalid_keys.map(&:inspect).join(', ')}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}#{caller_context}"
end

.validate_and_return(options, *valid_keys) ⇒ Hash

Helper method for backwards compatibility - allows gradual migration from Hash monkey patch to this module

Parameters:

  • options (Hash)

    The options to validate

  • valid_keys (Array<Symbol>)

    Valid keys

Returns:

  • (Hash)

    The same options hash (for chaining)



66
67
68
69
# File 'lib/state_machines/options_validator.rb', line 66

def validate_and_return(options, *valid_keys)
  assert_valid_keys!(options, *valid_keys)
  options
end

.validator(valid_keys: [], exclusive_key_groups: [], caller_info: nil) ⇒ Proc

Validates options using a more convenient interface that works with both hash-style and kwargs-style method definitions

Parameters:

  • valid_keys (Array<Symbol>) (defaults to: [])

    List of valid key names

  • exclusive_key_groups (Array<Array<Symbol>>) (defaults to: [])

    Groups of mutually exclusive keys

  • caller_info (String) (defaults to: nil)

    Information about the calling method

Returns:

  • (Proc)

    A validation proc that can be called with options



50
51
52
53
54
55
56
57
58
# File 'lib/state_machines/options_validator.rb', line 50

def validator(valid_keys: [], exclusive_key_groups: [], caller_info: nil)
  proc do |options|
    assert_valid_keys!(options, *valid_keys, caller_info: caller_info) unless valid_keys.empty?

    exclusive_key_groups.each do |group|
      assert_exclusive_keys!(options, *group, caller_info: caller_info)
    end
  end
end