philiprehberger-enum 0.1.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5765112f2fd16bde7ed19854cf3e60b11826676cc2f9745d55e538ee05b1d07f
4
- data.tar.gz: '0915d0457694b6de70cf61ff2193c30f21a408278a46613926e3c22ab830b61c'
3
+ metadata.gz: 3841094e2bc4093c7ee76058b058ffc2b99302c27b77c1c3e5b8724251a90f90
4
+ data.tar.gz: 769f7d79d66026f0f5aa6848e4845e36260d3fa5251085b453983410dc9ceadf
5
5
  SHA512:
6
- metadata.gz: 1ae93ae4f8bbeae4dcf07e1dbf1685317bab80c288256cacbebf582baa8d6baa7f5ca4fd8d51c32240b9a60ea01a046176aeee374013516882cbbd76af42108b
7
- data.tar.gz: 6ee8b1f10e6941d0d6c4d5ad56fe46f4d3b6d307842bd9bab85a352ddaa7a8fc29d38adf731cec8df4c69ba37c86958e5bccdbf2b493f4fed5303553fafddc47
6
+ metadata.gz: fc946c8e5d96461a2774036a34c569351a7fdda7514bf6389e97d928e0b393fd2c21b1ff4b53adae561242886dc1a028d3a5d4c01b305d202e9ee4780d7ae62b
7
+ data.tar.gz: 78d1dda7a94396755c7ff710d572b1f96710f9007af4bc8b66e55920e4e5e55e1ef8edd651c185f117d473807d7ef25b7f451fb53c6560f9317fcbcc3cc93f96
data/CHANGELOG.md CHANGED
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-04-09
11
+
12
+ ### Added
13
+ - `Enum.fetch(name)` strict lookup that raises `Error` if the name is not a member (case-insensitive fallback)
14
+ - `Enum.fetch_by_value(val)` strict value lookup that raises `Error` if no member has the given value
15
+ - `Enum.names` returns a frozen array of all member name symbols in declaration order
16
+ - `Enum.values` returns a frozen array of all member values in declaration order
17
+ - `Enum.first` / `Enum.last` return the first and last declared members
18
+
19
+ ## [0.2.0] - 2026-04-03
20
+
21
+ ### Added
22
+ - Include `Enumerable` at the class level with `each` yielding each member (`map`, `select`, `to_a`, etc.)
23
+ - `Enum.to_h` returns `{ name_symbol => value }` hash of all members
24
+ - `Enum.members_by_value` returns `{ value => member }` reverse lookup hash
25
+ - `Enum.size` / `Enum.count` returns the number of defined members
26
+
27
+ ### Changed
28
+ - `Enum.from_name` now falls back to case-insensitive matching when exact match fails
29
+
30
+ ## [0.1.6] - 2026-03-31
31
+
32
+ ### Added
33
+ - Add GitHub issue templates, dependabot config, and PR template
34
+
10
35
  ## [0.1.5] - 2026-03-31
11
36
 
12
37
  ### Changed
data/README.md CHANGED
@@ -62,6 +62,58 @@ Status.valid?(:draft) # => true
62
62
  Status.valid?(:unknown) # => false
63
63
  ```
64
64
 
65
+ ### Enumerable
66
+
67
+ Enum classes include `Enumerable`, so you can iterate, map, select, etc.:
68
+
69
+ ```ruby
70
+ Status.each { |member| puts member.name }
71
+ Status.map(&:name) # => [:draft, :published, :archived]
72
+ Status.select { |m| m.ordinal > 0 } # => [PUBLISHED, ARCHIVED]
73
+ Status.to_a # => [DRAFT, PUBLISHED, ARCHIVED]
74
+ Status.min # => DRAFT
75
+ ```
76
+
77
+ ### Collection Methods
78
+
79
+ ```ruby
80
+ Status.to_h # => { draft: nil, published: nil, archived: nil }
81
+ HttpCode.to_h # => { ok: 200, not_found: 404, server_error: 500 }
82
+ HttpCode.members_by_value # => { 200 => OK, 404 => NOT_FOUND, 500 => SERVER_ERROR }
83
+ Status.size # => 3
84
+ Status.count # => 3
85
+ ```
86
+
87
+ ### Strict Lookup
88
+
89
+ `fetch` and `fetch_by_value` raise an error instead of returning `nil`:
90
+
91
+ ```ruby
92
+ Status.fetch(:draft) # => Status::DRAFT
93
+ Status.fetch(:unknown) # raises Philiprehberger::Enum::Error
94
+ HttpCode.fetch_by_value(200) # => HttpCode::OK
95
+ HttpCode.fetch_by_value(999) # raises Philiprehberger::Enum::Error
96
+ ```
97
+
98
+ ### Names, Values, First & Last
99
+
100
+ ```ruby
101
+ HttpCode.names # => [:ok, :not_found, :server_error]
102
+ HttpCode.values # => [200, 404, 500]
103
+ Status.first # => Status::DRAFT
104
+ Status.last # => Status::ARCHIVED
105
+ ```
106
+
107
+ ### Case-Insensitive Lookup
108
+
109
+ `from_name` tries an exact match first, then falls back to case-insensitive:
110
+
111
+ ```ruby
112
+ Status.from_name(:draft) # => Status::DRAFT (exact match)
113
+ Status.from_name("DRAFT") # => Status::DRAFT (case-insensitive)
114
+ Status.from_name("Draft") # => Status::DRAFT (case-insensitive)
115
+ ```
116
+
65
117
  ### Comparison
66
118
 
67
119
  Members are comparable by ordinal:
@@ -97,7 +149,16 @@ Status::DRAFT.to_json # => '{"name":"draft","ordinal":0,"value":null}'
97
149
  |--------|-------------|
98
150
  | `.member(name, value: nil)` | Define a new enum member with optional custom value |
99
151
  | `.members` | Return all members in declaration order |
100
- | `.from_name(name)` | Look up a member by symbol or string name |
152
+ | `.each` | Yield each member (includes `Enumerable`) |
153
+ | `.to_h` | Return `{ name_symbol => value }` hash |
154
+ | `.members_by_value` | Return `{ value => member }` reverse lookup hash |
155
+ | `.size` / `.count` | Return the number of defined members |
156
+ | `.names` | Return a frozen array of member name symbols |
157
+ | `.values` | Return a frozen array of member values |
158
+ | `.first` / `.last` | Return the first or last declared member |
159
+ | `.fetch(name)` | Strict lookup by name; raises `Error` if not found |
160
+ | `.fetch_by_value(val)` | Strict lookup by value; raises `Error` if not found |
161
+ | `.from_name(name)` | Look up by name (case-insensitive fallback) |
101
162
  | `.from_string(string)` | Look up a member by string name |
102
163
  | `.from_value(val)` | Look up a member by custom value |
103
164
  | `.valid?(name)` | Check if a name is a valid member |
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  class Enum
5
- VERSION = '0.1.5'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
@@ -75,6 +75,17 @@ module Philiprehberger
75
75
  end
76
76
 
77
77
  class << self
78
+ include Enumerable
79
+
80
+ # Yield each member in declaration order
81
+ #
82
+ # @yield [Enum] each member
83
+ # @return [Enumerator] if no block given
84
+ def each(&)
85
+ freeze_members!
86
+ member_registry.values.each(&)
87
+ end
88
+
78
89
  # Define a new member on this enum class
79
90
  #
80
91
  # @param name [Symbol] the member name
@@ -104,13 +115,40 @@ module Philiprehberger
104
115
  member_registry.values.freeze
105
116
  end
106
117
 
107
- # Look up a member by its name
118
+ # Return a hash of name symbols to values
119
+ #
120
+ # @return [Hash{Symbol => Object}] name => value pairs
121
+ def to_h
122
+ freeze_members!
123
+ member_registry.transform_values(&:value)
124
+ end
125
+
126
+ # Return a reverse lookup hash of values to members
127
+ #
128
+ # @return [Hash{Object => Enum}] value => member pairs
129
+ def members_by_value
130
+ freeze_members!
131
+ member_registry.each_value.to_h { |m| [m.value, m] }
132
+ end
133
+
134
+ # Return the number of defined members
135
+ #
136
+ # @return [Integer] the member count
137
+ def size
138
+ freeze_members!
139
+ member_registry.size
140
+ end
141
+
142
+ alias count size
143
+
144
+ # Look up a member by its name, with case-insensitive fallback
108
145
  #
109
146
  # @param name [Symbol, String] the member name
110
147
  # @return [Enum, nil] the member, or nil if not found
111
148
  def from_name(name)
112
149
  freeze_members!
113
- member_registry[name.to_sym]
150
+ key = name.to_sym
151
+ member_registry[key] || member_registry.values.find { |m| m.name.to_s.downcase == key.to_s.downcase }
114
152
  end
115
153
 
116
154
  # Look up a member by its string representation
@@ -130,6 +168,56 @@ module Philiprehberger
130
168
  member_registry.values.find { |m| m.value == val }
131
169
  end
132
170
 
171
+ # Look up a member by name, raising if not found
172
+ #
173
+ # @param name [Symbol, String] the member name
174
+ # @return [Enum] the member
175
+ # @raise [Error] if the name is not a valid member
176
+ def fetch(name)
177
+ from_name(name) || raise(Error, "no member #{name.inspect} on #{self}")
178
+ end
179
+
180
+ # Look up a member by value, raising if not found
181
+ #
182
+ # @param val [Object] the value to search for
183
+ # @return [Enum] the member
184
+ # @raise [Error] if the value is not found
185
+ def fetch_by_value(val)
186
+ from_value(val) || raise(Error, "no member with value #{val.inspect} on #{self}")
187
+ end
188
+
189
+ # Return all member names in declaration order
190
+ #
191
+ # @return [Array<Symbol>] frozen array of member names
192
+ def names
193
+ freeze_members!
194
+ member_registry.keys.freeze
195
+ end
196
+
197
+ # Return all member values in declaration order
198
+ #
199
+ # @return [Array<Object>] frozen array of member values
200
+ def values
201
+ freeze_members!
202
+ member_registry.values.map(&:value).freeze
203
+ end
204
+
205
+ # Return the first declared member
206
+ #
207
+ # @return [Enum, nil] the first member, or nil if empty
208
+ def first
209
+ freeze_members!
210
+ member_registry.values.first
211
+ end
212
+
213
+ # Return the last declared member
214
+ #
215
+ # @return [Enum, nil] the last member, or nil if empty
216
+ def last
217
+ freeze_members!
218
+ member_registry.values.last
219
+ end
220
+
133
221
  # Check if a name is a valid member
134
222
  #
135
223
  # @param name [Symbol, String] the member name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philiprehberger-enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Rehberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-31 00:00:00.000000000 Z
11
+ date: 2026-04-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Define type-safe enums in Ruby with automatic ordinals, custom values,
14
14
  lookup methods, and Ruby 3.x pattern matching support. A cleaner alternative to
@@ -24,11 +24,11 @@ files:
24
24
  - README.md
25
25
  - lib/philiprehberger/enum.rb
26
26
  - lib/philiprehberger/enum/version.rb
27
- homepage: https://github.com/philiprehberger/rb-enum
27
+ homepage: https://philiprehberger.com/open-source-packages/ruby/philiprehberger-enum
28
28
  licenses:
29
29
  - MIT
30
30
  metadata:
31
- homepage_uri: https://github.com/philiprehberger/rb-enum
31
+ homepage_uri: https://philiprehberger.com/open-source-packages/ruby/philiprehberger-enum
32
32
  source_code_uri: https://github.com/philiprehberger/rb-enum
33
33
  changelog_uri: https://github.com/philiprehberger/rb-enum/blob/main/CHANGELOG.md
34
34
  bug_tracker_uri: https://github.com/philiprehberger/rb-enum/issues