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 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