typesafe_enum 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|