Class: Dux::Enum

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/dux/enum.rb

Overview

A set of strings or symbols (indifferently stored) that can be used to validate options.

Supports an optional default for when an invalid element is fetched to act as a fallback rather than raising an error.

Defined Under Namespace

Classes: AliasMap, InvalidAliasTargetError, InvalidFallback, MemberAsAliasError, NotFound

Constant Summary collapse

NO_DEFAULT =

NullObject to determine if we have no default value.

Dux.null 'Dux::Enum::NO_DEFAULT', purpose: 'When no default has been provided'
RETURN_TYPES =

Types that can be specified for a return type

%i[symbol string].freeze

Instance Method Summary collapse

Constructor Details

#initialize(*values, default: NO_DEFAULT, allow_nil: false, aliases: {}, return_type: :symbol) ⇒ Enum

Returns a new instance of Enum.



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/dux/enum.rb', line 23

def initialize(*values, default: NO_DEFAULT, allow_nil: false, aliases: {}, return_type: :symbol)
  @allow_nil = allow_nil

  set_return_type return_type

  set_values values

  set_default default

  set_aliases aliases

  freeze
end

Instance Method Details

#===(other) ⇒ Object

Test for inclusion with case equality

Parameters:

  • other (String, Symbol)


40
41
42
# File 'lib/dux/enum.rb', line 40

def ===(other)
  include? other
end

#alias?(key) ⇒ Boolean

Check if the provided key is an alias.

Parameters:

  • key (Symbol, String)

Returns:

  • (Boolean)


47
48
49
# File 'lib/dux/enum.rb', line 47

def alias?(key)
  @aliases.key? key
end

#allow_nil?Boolean

Check if we allow nil to be returned as a default / fallback.

Returns:

  • (Boolean)


53
54
55
# File 'lib/dux/enum.rb', line 53

def allow_nil?
  @allow_nil
end

#default?Boolean

Check if a default is set for this enum.

Returns:

  • (Boolean)


58
59
60
# File 'lib/dux/enum.rb', line 58

def default?
  @default != NO_DEFAULT
end

#each {|value| ... } ⇒ Object

Yields:

  • (value)

    each member of the enum

Yield Parameters:



64
65
66
67
68
69
70
# File 'lib/dux/enum.rb', line 64

def each
  return enum_for(__method__) unless block_given?

  @values.each do |value|
    yield value
  end
end

#fetch(value, fallback: NO_DEFAULT) { ... } ⇒ Symbol Also known as: []

Parameters:

  • value (String, Symbol)
  • fallback (String, Symbol) (defaults to: NO_DEFAULT)

Yields:

  • Executed in lieu of raising NotFound if there is an unknown member

Returns:

  • (Symbol)

Raises:



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/dux/enum.rb', line 78

def fetch(value, fallback: NO_DEFAULT)
  if include? value
    with_return_type value
  elsif alias?(value)
    with_return_type @aliases.fetch(value)
  elsif fallback != NO_DEFAULT
    if valid_fallback?(fallback)
      fallback
    else
      raise InvalidFallback, "Cannot use #{fallback.inspect} as a fallback"
    end
  elsif default?
    with_return_type @default
  else
    if block_given?
      yield value
    else
      raise NotFound, "Invalid enum member: #{value.inspect}"
    end
  end
end

#inspectString

Returns:

  • (String)


103
104
105
# File 'lib/dux/enum.rb', line 103

def inspect
  "Dux::Enum(#{@values.to_a.inspect})"
end

#set_aliases(aliases) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • aliases ({Symbol => String, Symbol})

Raises:

  • (TypeError)


155
156
157
158
159
# File 'lib/dux/enum.rb', line 155

def set_aliases(aliases)
  raise TypeError, 'Aliases must be a hash' unless aliases.kind_of?(Hash)

  @aliases = AliasMap.new *self, **aliases
end

#set_default(fallback) ⇒ void (private)

This method returns an undefined value.

Set the default fallback value.

Parameters:

  • fallback (String, Symbol, nil)


175
176
177
178
179
180
181
# File 'lib/dux/enum.rb', line 175

def set_default(fallback)
  if valid_fallback?(fallback) || fallback == NO_DEFAULT
    @default = fallback
  else
    raise InvalidFallback, "Cannot set #{fallback.inspect} as default", caller
  end
end

#set_return_type(return_type) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • return_type (Symbol)

Raises:

  • (ArgumentError)

    on improper return type



134
135
136
137
138
139
140
# File 'lib/dux/enum.rb', line 134

def set_return_type(return_type)
  if RETURN_TYPES.include? return_type
    @return_type = return_type
  else
    raise ArgumentError, "Invalid return type: #{return_type.inspect}", caller
  end
end

#set_values(values) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • values (<String, Symbol>)

Raises:

  • (TypeError)

    if provided with no values



145
146
147
148
149
150
151
# File 'lib/dux/enum.rb', line 145

def set_values(values)
  raise TypeError, "Must provide some values", caller if values.empty?

  @values = values.flatten.map do |value|
    Dux::IndifferentString.new value
  end.to_set.freeze
end

#valid_fallback?(fallback) ⇒ Boolean (private)

Check if the provided fallback is valid

Parameters:

  • fallback (String, Symbol, nil)

Returns:

  • (Boolean)


164
165
166
167
168
169
# File 'lib/dux/enum.rb', line 164

def valid_fallback?(fallback)
  return true if fallback.nil? && allow_nil?
  return true if include? fallback

  false
end

#with_return_type(value) ⇒ String, ... (private)

Ensure the value is returned with the correct type

Parameters:

  • value (String, Symbol, nil)

Returns:

  • (String, Symbol, nil)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/dux/enum.rb', line 115

def with_return_type(value)
  if value.nil? && allow_nil?
    if allow_nil?
      nil
    else
      # :nocov:
      raise ArgumentError, "Cannot return `nil` without allow_nil: true"
      # :nocov:
    end
  elsif @return_type == :symbol
    value.to_sym
  elsif @return_type == :string
    value.to_s
  end
end