typesafe_enum 0.1.0 → 0.1.1
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 +4 -4
- data/.gitignore +3 -0
- data/CHANGES.md +4 -0
- data/README.md +89 -10
- data/lib/typesafe_enum/base.rb +8 -0
- data/lib/typesafe_enum/module_info.rb +1 -1
- data/spec/unit/typesafe_enum/base_spec.rb +39 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59ddff44544a977b2f7d6c4cf56727d0a1aabf60
|
4
|
+
data.tar.gz: 9987d8367b1eb2cc2d79baa52b8ed58e934e5dd3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64736c736ebd281b5eb368195bef1bbcd62ea61f737d3474f8e29b4bfd468a376199fb62f0a639a16a68ff98af9a24293867720e790f6e6cd76282161165de64
|
7
|
+
data.tar.gz: 8dc8b5dcaa016a53bda462f425f77652745c11e36944172895f36924bd00e49ead3eff56463f9ad5150772f524a4e1a3d2ed740365fafdfd1aa21cf357b58f56
|
data/.gitignore
CHANGED
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -144,6 +144,19 @@ Tarot.find_by_ord(3)
|
|
144
144
|
# => #<Tarot:0x007faab19fd810 @key=:SWORDS, @value="Swords", @ord=3>
|
145
145
|
```
|
146
146
|
|
147
|
+
### `::find_by_value_str`
|
148
|
+
|
149
|
+
Look up an enum instance based on the string form of its value (as returned by `to_s`) --
|
150
|
+
useful for, e.g., XML or JSON mapping of enums with non-string values:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
Scale.find_by_value_str('1000000')
|
154
|
+
# => #<Scale:0x007f8513a93810 @key=:MEGA, @value=1000000, @ord=3>
|
155
|
+
```
|
156
|
+
|
157
|
+
(Note that unlike the other `::find_by…` methods, which use hash lookups, `::find_by_value_str`
|
158
|
+
is linear in the number of enum values, so it's best suited for smaller enumerations.)
|
159
|
+
|
147
160
|
## Enum classes with methods
|
148
161
|
|
149
162
|
Enum classes can have methods, and other non-enum constants:
|
@@ -259,33 +272,99 @@ Tarot::CUPS == 'Cups'
|
|
259
272
|
# => false
|
260
273
|
```
|
261
274
|
|
262
|
-
## How is this different from
|
263
|
-
|
264
|
-
*[TODO: details]*
|
275
|
+
## How is this different from `java.lang.Enum`?
|
265
276
|
|
266
277
|
### Clunkier syntax
|
267
278
|
|
279
|
+
In Java 5+, you can define an enum in one line and instance-specific methods with a pair of braces.
|
280
|
+
|
281
|
+
```java
|
282
|
+
enum CMYKColor {
|
283
|
+
CYAN, MAGENTA, YELLOW, BLACK
|
284
|
+
}
|
285
|
+
|
286
|
+
enum Suit {
|
287
|
+
CLUBS { char pip() { return '♣'; } },
|
288
|
+
DIAMONDS { char pip() { return '♦'; } },
|
289
|
+
HEARTS { char pip() { return '♥'; } },
|
290
|
+
SPADES { char pip() { return '♠'; } };
|
291
|
+
|
292
|
+
abstract char pip();
|
293
|
+
}
|
294
|
+
```
|
295
|
+
|
296
|
+
With `TypesafeEnum`, instance-specific methods require extra parentheses and `instance_eval`,
|
297
|
+
as shown above, and about the best you can do even for simple enums is something like:
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
class CMYKColor < TypesafeEnum::Base
|
301
|
+
[:CYAN, :MAGENTA, :YELLOW, :BLACK].each { |c| new c }
|
302
|
+
end
|
303
|
+
```
|
304
|
+
|
268
305
|
### No special `switch`/`case` support
|
269
306
|
|
307
|
+
The Java compiler will warn you if a `switch` statement doesn't include all instances of a Java enum.
|
308
|
+
Ruby doesn't care whether you cover all instances of a `TypesafeEnum`, and in fact it doesn't care if
|
309
|
+
your `when` statements include a mix of enum instances of different classes, or of enum instances and
|
310
|
+
other things. (In some respects this latter is a feature, of course.)
|
311
|
+
|
270
312
|
### No serialization support
|
271
313
|
|
272
|
-
|
314
|
+
The Java `Enum` class has special code to ensure that enum instances are deserialized to the existing
|
315
|
+
singleton constants. This can be done with Ruby [`Marshal`](http://ruby-doc.org/core-2.2.3/Marshal.html)
|
316
|
+
(by defining `marshal_load`) but it didn't seem worth the trouble, so a deserialized `TypesafeEnum` will
|
317
|
+
not be identical to the original:
|
273
318
|
|
274
|
-
|
275
|
-
|
319
|
+
```ruby
|
320
|
+
clubs2 = Marshal.load(Marshal.dump(Suit::CLUBS))
|
321
|
+
Suit::CLUBS.equal?(clubs2)
|
322
|
+
# => false
|
323
|
+
```
|
324
|
+
|
325
|
+
However, `#==`, `#hash`, etc. are `Marshal`-safe:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
Suit::CLUBS == clubs2
|
329
|
+
# => true
|
330
|
+
clubs2 == Suit::CLUBS
|
331
|
+
# => true
|
332
|
+
Suit::CLUBS.hash == clubs2.hash
|
333
|
+
# => true
|
334
|
+
```
|
335
|
+
|
336
|
+
If this isn't enough, and the lack of object identity across marshalling is a problem, it could be added
|
337
|
+
in a later version. (Pull requests welcome!)
|
338
|
+
|
339
|
+
### No support classes
|
340
|
+
|
341
|
+
Java has `Enum`-specific classes like
|
342
|
+
[`EnumSet`](http://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html) and
|
343
|
+
[`EnumMap`](http://docs.oracle.com/javase/8/docs/api/java/util/EnumMap.html) that provide special
|
344
|
+
high-performance, optimized versions of its collection interfaces. `TypesafeEnum` doesn't.
|
276
345
|
|
277
346
|
### Enum classes are not closed
|
278
347
|
|
279
348
|
It's Ruby, so even though `:new` is private to each enum class, you
|
280
|
-
can
|
349
|
+
can work around that in various ways:
|
281
350
|
|
282
351
|
```ruby
|
283
352
|
Suit.send(:new, :JOKERS)
|
284
353
|
# => #<Suit:0x007fc9e44e4778 @key=:JOKERS, @value="jokers", @ord=4>
|
354
|
+
|
355
|
+
class Tarot
|
356
|
+
new :MAJOR_ARCANA, 'Major Arcana'
|
357
|
+
end
|
358
|
+
# => #<Tarot:0x007f8513b39b20 @key=:MAJOR_ARCANA, @value="Major Arcana", @ord=4>
|
359
|
+
|
285
360
|
Suit.map(&:key)
|
286
361
|
# => [:CLUBS, :DIAMONDS, :HEARTS, :SPADES, :JOKERS]
|
287
|
-
|
288
|
-
|
362
|
+
|
363
|
+
Tarot.map(&:key)
|
364
|
+
# => [:CUPS, :COINS, :WANDS, :SWORDS, :MAJOR_ARCANA]
|
289
365
|
```
|
290
366
|
|
291
|
-
|
367
|
+
## Contributing
|
368
|
+
|
369
|
+
Pull requests are welcome, but please make sure the tests pass, the code has 100% coverage, and the
|
370
|
+
code style passes Rubocop. (The default rake task should check all of these for you.)
|
data/lib/typesafe_enum/base.rb
CHANGED
@@ -42,6 +42,14 @@ module TypesafeEnum
|
|
42
42
|
by_value[value]
|
43
43
|
end
|
44
44
|
|
45
|
+
# Looks up an enum instance based on the string representation of its value
|
46
|
+
def find_by_value_str(value_str)
|
47
|
+
value_str = value_str.to_s
|
48
|
+
by_value.each do |value, instance|
|
49
|
+
return instance if value_str == value.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
45
53
|
# Looks up an enum instance based on its ordinal
|
46
54
|
def find_by_ord(ord)
|
47
55
|
return nil if ord < 0 || ord > size
|
@@ -15,6 +15,19 @@ class Tarot < TypesafeEnum::Base
|
|
15
15
|
new :SWORDS, 'Swords'
|
16
16
|
end
|
17
17
|
|
18
|
+
class RGBColor < TypesafeEnum::Base
|
19
|
+
new :RED, :red
|
20
|
+
new :GREEN, :green
|
21
|
+
new :BLUE, :blue
|
22
|
+
end
|
23
|
+
|
24
|
+
class Scale < TypesafeEnum::Base
|
25
|
+
new :DECA, 10
|
26
|
+
new :HECTO, 100
|
27
|
+
new :KILO, 1_000
|
28
|
+
new :MEGA, 1_000_000
|
29
|
+
end
|
30
|
+
|
18
31
|
module TypesafeEnum
|
19
32
|
describe Base do
|
20
33
|
|
@@ -285,27 +298,40 @@ module TypesafeEnum
|
|
285
298
|
end
|
286
299
|
|
287
300
|
it 'supports enums with symbol values' do
|
288
|
-
|
289
|
-
|
290
|
-
new :GREEN, :green
|
291
|
-
new :BLUE, :blue
|
301
|
+
RGBColor.each do |c|
|
302
|
+
expect(RGBColor.find_by_value(c.value)).to be(c)
|
292
303
|
end
|
304
|
+
end
|
293
305
|
|
294
|
-
|
295
|
-
|
306
|
+
it 'supports enums with integer values' do
|
307
|
+
Scale.each do |s|
|
308
|
+
expect(Scale.find_by_value(s.value)).to be(s)
|
296
309
|
end
|
297
310
|
end
|
311
|
+
end
|
298
312
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
313
|
+
describe '::find_by_value_str' do
|
314
|
+
it 'maps string values to enum instances' do
|
315
|
+
values = %w(clubs diamonds hearts spades)
|
316
|
+
expected = Suit.to_a
|
317
|
+
values.each_with_index do |n, index|
|
318
|
+
expect(Suit.find_by_value_str(n)).to be(expected[index])
|
305
319
|
end
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'returns nil for invalid values' do
|
323
|
+
expect(Suit.find_by_value_str('wands')).to be_nil
|
324
|
+
end
|
306
325
|
|
326
|
+
it 'supports enums with symbol values' do
|
327
|
+
RGBColor.each do |c|
|
328
|
+
expect(RGBColor.find_by_value_str(c.value.to_s)).to be(c)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'supports enums with integer values' do
|
307
333
|
Scale.each do |s|
|
308
|
-
expect(Scale.
|
334
|
+
expect(Scale.find_by_value_str(s.value.to_s)).to be(s)
|
309
335
|
end
|
310
336
|
end
|
311
337
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typesafe_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Moles
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|