nummy 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +80 -0
- data/README.md +54 -2
- data/lib/nummy/enum.rb +75 -0
- data/lib/nummy/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83fe6928d06ebd4ba649eaa37ad3278366e2322a99fe56a7efdfed228b971841
|
4
|
+
data.tar.gz: 7116e7d5febca95ae52544bcbc42a4fd99e895ca8e60ef9cd7e3444e6dae8719
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d4bb886ad7d5187aca88391c1e9366a82b4bdb08e435cb5567951a5e2a5e5d230ef5f06cdae0bd5b104c8a62d00e41c437969cf9b9b4a4cf7d5eb41e73dd4ac
|
7
|
+
data.tar.gz: dc40fbde79187708d1006bd80475b114f98f8de238faaae8bd4a9b620f5557df06c3d960123e237267041370f59baee13d42e1f4389e97e3394e68fe6e383cfc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,85 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2024-01-04
|
4
|
+
|
5
|
+
- **Adds additional flexibility to `Nummy::Enum.to_attribute` (#2)
|
6
|
+
|
7
|
+
This release teaches a few new tricks to `Nummy::Enum.to_attribute`:
|
8
|
+
|
9
|
+
- it allows passing a block to fully customize how keys are transformed
|
10
|
+
|
11
|
+
- it looks for `String#underscore` rather than calling into `ActiveSupport::Inflector.underscore` directly, which means that users can bring their own monkey patch if they want to.
|
12
|
+
|
13
|
+
- it falls back to `Symbol#downcase` if `String#underscore` is not available. If the constants are defined using `SCREAMING_SNAKE_CASE`, this will generally have the same result as calling `String#underscore`, but without requiring ActiveSupport.
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class ShippingStatus < Nummy::Enum
|
17
|
+
IN_TRANSIT = auto
|
18
|
+
OUT_FOR_DELIVERY = auto
|
19
|
+
DELIVERED = auto
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# Without ActiveSupport
|
25
|
+
|
26
|
+
ShippingStatus.to_attribute
|
27
|
+
# v0.2.0 (❌)
|
28
|
+
# => nummy/lib/nummy/enum.rb:379:in `block in to_attribute': uninitialized constant ActiveSupport (NameError)
|
29
|
+
#
|
30
|
+
# ::ActiveSupport::Inflector.underscore(key).to_sym
|
31
|
+
# ^^^^^^^^^^^^^^^
|
32
|
+
|
33
|
+
# v0.3.0 (✅)
|
34
|
+
# => {:in_transit=>0, :out_for_delivery=>1, :delivered=>2}
|
35
|
+
```
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# With ActiveSupport
|
39
|
+
require "active_support/core_ext/string/inflections"
|
40
|
+
|
41
|
+
ShippingStatus.to_attribute
|
42
|
+
# => {:in_transit=>0, :out_for_delivery=>1, :delivered=>2}
|
43
|
+
|
44
|
+
ShippingStatus.to_attribute { |key| key.to_s.underscore.camelize.to_sym }
|
45
|
+
# => {:InTransit=>0, :OutForDelivery=>1, :Delivered=>2}
|
46
|
+
```
|
47
|
+
|
48
|
+
- **Adds JSON serialization support (#3)**
|
49
|
+
|
50
|
+
This release adds two methods to `Nummy::Enum`: `.as_json` and `.to_json`. These methods allow you to serialize an enum to JSON.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class Status < Nummy::Enum
|
54
|
+
ACTIVE = auto
|
55
|
+
ARCHIVED = auto
|
56
|
+
end
|
57
|
+
|
58
|
+
Status.as_json
|
59
|
+
# => {"ACTIVE" => 0, "ARCHIVED" => 1}
|
60
|
+
|
61
|
+
Status.to_json
|
62
|
+
# => "{\"ACTIVE\":0,\"ARCHIVED\":1}
|
63
|
+
```
|
64
|
+
|
65
|
+
## [0.2.0] - 2024-01-04
|
66
|
+
|
67
|
+
- Add `Nummy::Enum.to_attribute` (#1), which converts the enum to a hash that can be passed as the values of an `ActiveRecord::Enum`:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
class Conversation < ActiveRecord::Base
|
71
|
+
class Status < Nummy::Enum
|
72
|
+
ACTIVE = auto
|
73
|
+
ARCHIVED = auto
|
74
|
+
end
|
75
|
+
|
76
|
+
enum :status, Status.to_attribute
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
> [!IMPORTANT]
|
81
|
+
> The conversion requires that `ActiveRecord::Inflector` is defined, but `nummy` does not depend on `ActiveRecord` directly. If you are using `nummy` in a non-Rails environment, you will need to require `ActiveRecord::Inflector` yourself.
|
82
|
+
|
3
83
|
## [0.1.0] - 2024-01-04
|
4
84
|
|
5
85
|
- Initial release
|
data/README.md
CHANGED
@@ -14,13 +14,13 @@ constants in a module, and iterating over the members of data classes.
|
|
14
14
|
Install the gem and add to the application's Gemfile by executing:
|
15
15
|
|
16
16
|
```console
|
17
|
-
bundle add
|
17
|
+
bundle add nummy
|
18
18
|
```
|
19
19
|
|
20
20
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
21
21
|
|
22
22
|
```console
|
23
|
-
gem install
|
23
|
+
gem install nummy
|
24
24
|
```
|
25
25
|
|
26
26
|
## Usage
|
@@ -146,6 +146,58 @@ end
|
|
146
146
|
> [!TIP]
|
147
147
|
> `Nummy::Enum` extends `Enumerable` and iterates over the _values_ of the enum, so you have access to things like `.include?(value)`, `.any?`, and `.find`.
|
148
148
|
|
149
|
+
#### Rails / ActiveRecord integration
|
150
|
+
|
151
|
+
To use nummy enums as ActiveRecord enums, you can use the `.to_attribute` method, which converts the keys to `snake_case` by default:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
class Conversation < ActiveRecord::Base
|
155
|
+
class Status < Nummy::Enum
|
156
|
+
ACTIVE = auto
|
157
|
+
ARCHIVED = auto
|
158
|
+
end
|
159
|
+
|
160
|
+
enum :status, Status.to_attribute
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
> [!NOTE]
|
165
|
+
> `to_attribute` will transform keys using `String#underscore` if it is defined, otherwise it will use `Symbol#downcase`.
|
166
|
+
|
167
|
+
> [!TIP]
|
168
|
+
> You can also do custom transformations by passing a block to `to_attribute`. See the documentation for more details.
|
169
|
+
|
170
|
+
Using `to_attribute` allows you to use all of the Rails magic for enums, like scopes and boolean helpers, while also being able to refer to values in a safer way than hash lookups.
|
171
|
+
|
172
|
+
That is, these two are the same:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
Conversation.statuses[:active] # => 0
|
176
|
+
Conversation::Status::ACTIVE # => 0
|
177
|
+
```
|
178
|
+
|
179
|
+
But these are not:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
Conversation.statuses[:acitve]
|
183
|
+
# => nil
|
184
|
+
|
185
|
+
Conversation::Status::ACITVE # => nil
|
186
|
+
# =>
|
187
|
+
# uninitialized constant Conversation::Status::ACITVE (NameError)
|
188
|
+
# Did you mean? Conversation::Status::ACTIVE
|
189
|
+
```
|
190
|
+
|
191
|
+
You can get similar behavior using `#fetch`:
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
Conversation.statuses.fetch(:acitve)
|
195
|
+
# => key not found: :acitve (KeyError)
|
196
|
+
# Did you mean? :active
|
197
|
+
```
|
198
|
+
|
199
|
+
But that still misses out on some of the DX benefits of using constants, like improved support for things like autocompletion, documentation, and navigation ("Go To Definition") in editors.
|
200
|
+
|
149
201
|
### `Nummy::MemberEnumerable`
|
150
202
|
|
151
203
|
`Nummy::MemberEnumerable` is a module that includes `Enumerable` and makes it possible to iterate over any class or module that responds to `members`.
|
data/lib/nummy/enum.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "json"
|
4
|
+
|
3
5
|
require "nummy/auto_sequenceable"
|
4
6
|
require "nummy/ordered_const_enumerable"
|
5
7
|
require "nummy/errors"
|
@@ -354,6 +356,79 @@ module Nummy
|
|
354
356
|
# Alias to support splatting enums into keyword args.
|
355
357
|
alias to_hash to_h
|
356
358
|
|
359
|
+
# Converts +self+ to a +Hash+ that can be converted to JSON.
|
360
|
+
#
|
361
|
+
# @return [Hash{String => Object}]
|
362
|
+
#
|
363
|
+
# @see .to_json
|
364
|
+
def as_json
|
365
|
+
to_h.transform_keys!(&:to_s)
|
366
|
+
end
|
367
|
+
|
368
|
+
# Converts +self+ to a +Hash+ and serializes it to a JSON string.
|
369
|
+
#
|
370
|
+
# Supports same options as +JSON#generate+.
|
371
|
+
#
|
372
|
+
# @return [String]
|
373
|
+
#
|
374
|
+
# @see .as_json
|
375
|
+
def to_json(*)
|
376
|
+
as_json.to_json(*)
|
377
|
+
end
|
378
|
+
|
379
|
+
# Converts the enum to a +Hash+ with snake_case keys.
|
380
|
+
#
|
381
|
+
# This is intended to be used with +ActiveRecord::Enum+, but can be used
|
382
|
+
# with any library that supports defining enums using a +Hash+ and expects
|
383
|
+
# to have lowercase keys.
|
384
|
+
#
|
385
|
+
# @overload to_attribute
|
386
|
+
# If +String#underscore+ is defined, converts the keys to snake_case
|
387
|
+
# by calling +underscore+ on the stringified key.
|
388
|
+
#
|
389
|
+
# Otherwise, converts each key using +Symbol#downcase+.
|
390
|
+
#
|
391
|
+
# @return [Hash{Symbol => Object}]
|
392
|
+
#
|
393
|
+
# @example Using with +ActiveRecord::Enum+.
|
394
|
+
# class Conversation < ActiveRecord::Base
|
395
|
+
# class Status < Nummy::Enum
|
396
|
+
# ACTIVE = auto
|
397
|
+
# ARCHIVED = auto
|
398
|
+
# end
|
399
|
+
#
|
400
|
+
# enum :status, Status.to_attribute
|
401
|
+
# end
|
402
|
+
#
|
403
|
+
# @overload to_attribute(&)
|
404
|
+
# Transforms the keys by calling the given block on each key.
|
405
|
+
#
|
406
|
+
# @yieldparam key [Symbol]
|
407
|
+
# @return [Hash{Symbol => Object}]
|
408
|
+
#
|
409
|
+
# @example Using custom key transformer.
|
410
|
+
# class ShippingStatus < Nummy::Enum
|
411
|
+
# IN_TRANSIT = auto
|
412
|
+
# OUT_FOR_DELIVERY = auto
|
413
|
+
# DELIVERED = auto
|
414
|
+
# end
|
415
|
+
#
|
416
|
+
# ShippingStatus.to_attribute { |key| key.to_s.underscore.camelize.to_sym }
|
417
|
+
# # => {:InTransit=>0, :OutForDelivery=>1, :Delivered=>2}
|
418
|
+
def to_attribute(&)
|
419
|
+
return to_h.transform_keys!(&) if block_given?
|
420
|
+
|
421
|
+
# Ignore coverage because it's executed in a forked process, which
|
422
|
+
# messes with the coverage collection.
|
423
|
+
# :nocov:
|
424
|
+
if String.method_defined?(:underscore)
|
425
|
+
return to_attribute { |key| key.to_s.underscore.to_sym }
|
426
|
+
end
|
427
|
+
# :nocov:
|
428
|
+
|
429
|
+
to_attribute(&:downcase)
|
430
|
+
end
|
431
|
+
|
357
432
|
# Returns a string representation of +self+.
|
358
433
|
#
|
359
434
|
# The string will contain the name-value pairs of the constants in +self+.
|
data/lib/nummy/version.rb
CHANGED