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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e6e6d0a15330f5ec2dd13061e2da603ec354705
4
- data.tar.gz: cfaca6a2bc5a2dd50dd2442abc23a6fe5775e8dd
3
+ metadata.gz: 59ddff44544a977b2f7d6c4cf56727d0a1aabf60
4
+ data.tar.gz: 9987d8367b1eb2cc2d79baa52b8ed58e934e5dd3
5
5
  SHA512:
6
- metadata.gz: 0808cf4b53fc63cd69d330cec45fe2124f73380070e6db5d7c6c03e389f8dbf32d1b9c36ea54147cbe6f2abfcc458b35416371f1242c17d191208e91342033ad
7
- data.tar.gz: 604dfd70e95d123a72045757aba249b474c3cb8869282d4eac3d38dd37663a56e5f7724439de1dafc20532b8d2eb79bb813fff60fad22064ac5229dd050df7c7
6
+ metadata.gz: 64736c736ebd281b5eb368195bef1bbcd62ea61f737d3474f8e29b4bfd468a376199fb62f0a639a16a68ff98af9a24293867720e790f6e6cd76282161165de64
7
+ data.tar.gz: 8dc8b5dcaa016a53bda462f425f77652745c11e36944172895f36924bd00e49ead3eff56463f9ad5150772f524a4e1a3d2ed740365fafdfd1aa21cf357b58f56
data/.gitignore CHANGED
@@ -15,6 +15,9 @@
15
15
  *.a
16
16
  mkmf.log
17
17
 
18
+ # Build output
19
+ *.gem
20
+
18
21
  # Database
19
22
 
20
23
  db/*.sqlite3
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.1
2
+
3
+ - Added `::find_by_value_str`
4
+
1
5
  ## 0.1.0
2
6
 
3
7
  - Initial release
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 [java.lang.Enum](http://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html)?
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
- - but `#==`, `#hash` etc. are `Marshal`-safe
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
- ### No support classes like [`EnumSet`](http://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html) and
275
- [`EnumMap`](http://docs.oracle.com/javase/8/docs/api/java/util/EnumMap.html)
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 always work around that:
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
- Suit.size
288
- # => 5
362
+
363
+ Tarot.map(&:key)
364
+ # => [:CUPS, :COINS, :WANDS, :SWORDS, :MAJOR_ARCANA]
289
365
  ```
290
366
 
291
- ### *[Other limitations...]*
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.)
@@ -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
@@ -3,7 +3,7 @@ module TypesafeEnum
3
3
  NAME = 'typesafe_enum'
4
4
 
5
5
  # The version of this gem
6
- VERSION = '0.1.0'
6
+ VERSION = '0.1.1'
7
7
 
8
8
  # The copyright notice for this gem
9
9
  COPYRIGHT = 'Copyright (c) 2015 The Regents of the University of California'
@@ -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
- class RGBColors < Base
289
- new :RED, :red
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
- RGBColors.each do |c|
295
- expect(RGBColors.find_by_value(c.value)).to be(c)
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
- it 'supports enums with integer values' do
300
- class Scale < Base
301
- new :DECA, 10
302
- new :HECTO, 100
303
- new :KILO, 1_000
304
- new :MEGA, 1_000_000
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.find_by_value(s.value)).to be(s)
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.0
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-18 00:00:00.000000000 Z
11
+ date: 2015-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler