Class: IS::Enum
- Inherits:
-
Object
- Object
- IS::Enum
- Extended by:
- Enumerable
- Includes:
- Comparable
- Defined in:
- lib/is-enum.rb,
lib/is-enum/info.rb
Overview
Thread safety
Enum definition (Enum.define) and finalization (Enum.finalize!) are thread-safe. Lookup operations are thread-safe after definition.
Class variables
Uses class variables ( @@enums, @@mutex ) shared across inheritance hierarchy. All enum classes register in global @@enums for Enum.parse.
Custom attributes
Additional attributes passed to Enum.define are stored in ‘@attrs`. Subclasses may access this hash directly to implement custom properties.
class Status < IS::Enum
define :error, 1, http_code: 500, retryable: false
def http_code
@attrs[:http_code]
end
def retryable?
@attrs[:retryable]
end
end
Defined Under Namespace
Modules: Info
Instance Attribute Summary collapse
-
#description ⇒ String?
readonly
Optional value description.
-
#name ⇒ Symbol
readonly
Value name.
-
#order_no ⇒ Integer
readonly
Order No for sorting and comparison.
Conversion collapse
-
.from(value) ⇒ IS::Enum, ...
Converts various types to enum values.
-
.of(name) ⇒ IS::Enum
Strict lookup by name.
-
.parse(source) ⇒ IS::Enum
In specific enum class: get enum value by name; in Enum itself: parse string like “Class.name” to enum value.
-
#inspect ⇒ String
Detailed inspection string with class, name, order_no and attributes.
-
#to_s ⇒ String
Name as string.
-
#to_sym ⇒ Symbol
Name as symbol.
Collection collapse
-
.[](name_or_order) ⇒ IS::Enum?
Lookup by name or order number.
-
.aliases ⇒ Hash<Symbol, IS::Enum>
Hash of alias names to target values.
- .each ⇒ Enumerator, self
-
.first ⇒ IS::Enum?
First value by order_no, or nil if empty.
-
.last ⇒ IS::Enum?
Last value by order_no, or nil if empty.
- .to_a(range = nil) ⇒ Array<IS::Enum>
-
.to_h ⇒ Hash<Symbol => IS::Enum>
Hash of all names and aliases.
-
.to_range ⇒ Range<IS::Enum>
Range from first to last value.
- .values ⇒ Array<IS::Enum>
Ordering collapse
-
#<=>(other) ⇒ Integer?
Returns
1if self > other;0if self == other;-1if self < other. -
#succ ⇒ IS::Enum?
Returns the next value by order_no, or nil if last.
Instance Attribute Details
#description ⇒ String? (readonly)
Returns optional value description.
298 299 300 |
# File 'lib/is-enum.rb', line 298 def description @description end |
#name ⇒ Symbol (readonly)
Returns value name.
295 296 297 |
# File 'lib/is-enum.rb', line 295 def name @name end |
#order_no ⇒ Integer (readonly)
Non-unique order numbers Multiple values may be defined with the same order_no. This affects sorting order (undefined when equal) and comparison behavior. See #<=> for comparison semantics.
Order No for sorting and comparison
292 293 294 |
# File 'lib/is-enum.rb', line 292 def order_no @order_no end |
Class Method Details
.[](name_or_order) ⇒ IS::Enum?
Lookup by name or order number. Returns nil if not found. See of for strict lookup that raises on missing value
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/is-enum.rb', line 117 def [](name_or_order) case name_or_order when String, Symbol key = name_or_order.to_sym @values[key] || @aliases[key] when Integer @values.values.find { |v| v.order_no == name_or_order } else raise ArgumentError, "Invalid value for name or order_no: #{name_or_order.inspect}", caller_locations end end |
.aliases ⇒ Hash<Symbol, IS::Enum>
Returns hash of alias names to target values.
142 143 144 |
# File 'lib/is-enum.rb', line 142 def aliases @aliases end |
.each ⇒ Enumerator, self
130 131 132 133 134 |
# File 'lib/is-enum.rb', line 130 def each return to_enum(__method__) unless block_given? values.each { |v| yield v } self end |
.first ⇒ IS::Enum?
Returns first value by order_no, or nil if empty.
152 153 154 |
# File 'lib/is-enum.rb', line 152 def first values.first end |
.from(value) ⇒ IS::Enum, ...
Converts various types to enum values.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/is-enum.rb', line 89 def from value case value when nil nil when self value when Range Range::new from(value.begin), from(value.end), value.exclude_end? when Set Set[*value.map { |v| from(v) }] when Enumerable value.map { |v| from(v) } else result = self[value] raise ArgumentError, "Invalid value of #{ self }: #{ value.inspect }", caller_locations unless result result end end |
.last ⇒ IS::Enum?
Returns last value by order_no, or nil if empty.
147 148 149 |
# File 'lib/is-enum.rb', line 147 def last values.last end |
.of(name) ⇒ IS::Enum
Strict lookup by name. Raises if not found. See [] for lenient lookup
74 75 76 77 78 79 |
# File 'lib/is-enum.rb', line 74 def of name raise ArgumentError, "Invalid name of #{ self }: #{ name.inspect }" unless name.is_a?(Symbol) val = @values[name] || @aliases[name] raise ArgumentError, "Invalid name of #{ self }: #{ name }" unless val return val end |
.parse(source) ⇒ IS::Enum
Security consideration Converts strings to Symbols internally. Do not use with untrusted user input to avoid memory exhaustion from symbol creation.
In specific enum class: get enum value by name; in IS::Enum itself: parse string like “Class.name” to enum value.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/is-enum.rb', line 51 def parse source raise ArgumentError, "Invalid source for parsing: #{ source.inspect }", caller_locations unless source.is_a?(String) if self == IS::Enum parts = source.split '.' raise ArgumentError, "Parsing error from #{ source.inspect }", caller_locations unless parts.is_a?(Array) && parts.size == 2 cls = @@enums[parts[0]] raise ArgumentError, "Enum class not found: #{ parts[0] }", caller_locations unless cls val = cls[parts[1].to_sym] raise ArgumentError, "#{ cls.name } value not found: #{ parts[1] }", caller_locations unless val return val else val = self[source.to_sym] raise ArgumentError, "#{ self.name } value not found: #{ source }", caller_locations unless val return val end end |
.to_a(range = nil) ⇒ Array<IS::Enum>
170 171 172 173 174 |
# File 'lib/is-enum.rb', line 170 def to_a range = nil return values unless range raise ArgumentError, "Invalid 'range' argument: #{ range.inspect }", caller_locations unless range.is_a?(Range) values.select { |item| (range.begin.nil? || item >= range.begin) && (range.end.nil? || item < range.end || (!range.exclude_end? && item == range.end)) } end |
.to_h ⇒ Hash<Symbol => IS::Enum>
Both canonical names and aliases are included. To distinguish, check aliases for alias keys.
Returns hash of all names and aliases.
164 165 166 |
# File 'lib/is-enum.rb', line 164 def to_h @values.merge(@aliases) end |
.to_range ⇒ Range<IS::Enum>
Returns range from first to last value.
157 158 159 |
# File 'lib/is-enum.rb', line 157 def to_range (first .. last) end |
.values ⇒ Array<IS::Enum>
137 138 139 |
# File 'lib/is-enum.rb', line 137 def values @sorted ||= @values.values.sort_by { |v| v.order_no } end |
Instance Method Details
#<=>(other) ⇒ Integer?
Comparison semantics ‘==` and `<=>` compare by order_no, while eql? compares object identity. Multiple values may share the same order_no; they compare as equal but are distinct objects.
class Alpha < IS::Enum
define :alpha, 10
define :beta, 20
define :bi, 20
define :Gamma, 30
define :g_letter, alias: :Gamma
end
Alpha.beta == Alpha.bi # => true (same order_no: 20)
Alpha.beta.eql?(Alpha.bi) # => false (different objects)
Alpha.Gamma.eql?(Alpha.g_letter) # => true (alias is same object)
Returns 1 if self > other; 0 if self == other; -1 if self < other. nil if other is not same type.
329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/is-enum.rb', line 329 def <=> other case other when self.class self.order_no <=> other.order_no when Symbol, String self.order_no <=> self.class[other.to_sym]&.order_no when Integer self.order_no <=> other else nil end end |
#inspect ⇒ String
Returns detailed inspection string with class, name, order_no and attributes.
364 365 366 367 368 369 370 371 |
# File 'lib/is-enum.rb', line 364 def inspect data = [ "#{ self.class }.#{ self.name }", "order_no=#{ @order_no }" ] data << "description=#{ @description.inspect }" if @description @attrs.each do |key, value| data << "#{ key }=#{ value.inspect }" end "[enum #{ data.join(' ') }]" end |
#succ ⇒ IS::Enum?
Returns the next value by order_no, or nil if last.
345 346 347 |
# File 'lib/is-enum.rb', line 345 def succ self.class.values.find { |v| v.order_no > self.order_no } end |
#to_s ⇒ String
Returns name as string.
359 360 361 |
# File 'lib/is-enum.rb', line 359 def to_s name.to_s end |
#to_sym ⇒ Symbol
Returns name as symbol.
354 355 356 |
# File 'lib/is-enum.rb', line 354 def to_sym name end |