finishing_moves 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 70d5165e29dbddcb1383c9216698d22a734e8394
4
+ data.tar.gz: 0a7bea820fa4b2a2423f20f43ab2ca9243393dd8
5
+ SHA512:
6
+ metadata.gz: 823eb4ebc4605b5cad2e3dcfb1ed2609ffb789bd5169c8c9d59bce26733924f125844148a7478a555e8afe5da9556c106e8aa50c867c0e44862f720747a75f20
7
+ data.tar.gz: 308f6cc084cb11a58e110021e2dc73967cd4db7e51eeb3bb57ff41f7b95d8e0f86819a544f1e1fc94b6a7e7caff600aa65177bfe0344c49d0aa70f0ebf30c922
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format Fuubar
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ finishing_moves (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ byebug (3.5.1)
10
+ columnize (~> 0.8)
11
+ debugger-linecache (~> 1.2)
12
+ slop (~> 3.6)
13
+ coderay (1.1.0)
14
+ colorize (0.7.3)
15
+ columnize (0.8.9)
16
+ debugger-linecache (1.2.0)
17
+ diff-lcs (1.2.5)
18
+ fuubar (2.0.0)
19
+ rspec (~> 3.0)
20
+ ruby-progressbar (~> 1.4)
21
+ method_source (0.8.2)
22
+ priscilla (1.0.3)
23
+ colorize (~> 0.7)
24
+ rumoji (~> 0.3)
25
+ pry (0.10.1)
26
+ coderay (~> 1.1.0)
27
+ method_source (~> 0.8.1)
28
+ slop (~> 3.4)
29
+ pry-byebug (2.0.0)
30
+ byebug (~> 3.4)
31
+ pry (~> 0.10)
32
+ rb-readline (0.5.1)
33
+ rspec (3.1.0)
34
+ rspec-core (~> 3.1.0)
35
+ rspec-expectations (~> 3.1.0)
36
+ rspec-mocks (~> 3.1.0)
37
+ rspec-core (3.1.7)
38
+ rspec-support (~> 3.1.0)
39
+ rspec-expectations (3.1.2)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.1.0)
42
+ rspec-mocks (3.1.3)
43
+ rspec-support (~> 3.1.0)
44
+ rspec-support (3.1.2)
45
+ ruby-progressbar (1.7.0)
46
+ rumoji (0.4.0)
47
+ slop (3.6.0)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ finishing_moves!
54
+ fuubar
55
+ priscilla
56
+ pry-byebug
57
+ rb-readline
58
+ rspec (~> 3.1.0)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Forge Software
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,602 @@
1
+ # Finishing Moves
2
+
3
+ ##### By the guys at [Forge Software](http://www.forgecrafted.com/)
4
+
5
+ Ruby includes a huge amount of default awesomeness that tackles most common development challenges. But every now and then, you find yourself in a situation where an *elaborate-yet-precise* coding maneuver wins the day. Finishing Moves is a collection of methods designed to assist in those just-typical-enough-to-be-annoying scenarios.
6
+
7
+ In gamer terms, if standard Ruby methods are your default moves, `finishing_moves` would be mana-consuming techniques. Your cooldown spells. Your grenades (there's never enough grenades). In the right situation, they kick serious cyclomatic butt.
8
+
9
+ ## Development approach
10
+
11
+ - **Never** override default Ruby behavior, only add functionality. No hacks.
12
+ - Follow the Unix philosophy of *"Do one job really well."*
13
+ - Minimize assumptions within the method, e.g. avoid formatting output, mutating values, and long conditional logic flows.
14
+ - Test all the things.
15
+
16
+ ## Installation
17
+
18
+ ```
19
+ (Gemification coming soon!)
20
+ ```
21
+
22
+ ## Current Finishers
23
+
24
+ ### Extensions to `Object`
25
+
26
+ #### `Object#nil_chain`
27
+ Arguably the sharpest knife in the block, `#nil_chain` allows you to write elaborate method chains without fear of tripping over `NoMethodError` and `NameError` exceptions when something in the chain throws out a nil value.
28
+
29
+ ##### Examples
30
+
31
+ ```ruby
32
+ # foobar may have a transmogrify method...or it may not! Doooooom!
33
+
34
+ # without nil_chain, we check to make sure the method exists
35
+
36
+ foobar.transmogrify if foobar.respond_to? :transmogrify
37
+
38
+ # with nil_chain, we just do it, and kick those nil ghosts in the teeth
39
+
40
+ nil_chain{ foobar.transmogrify }
41
+ # => result of foobar.transmogrify, or nil
42
+ ```
43
+
44
+ Not really saving much typing there, but how about an object assigned to a hash?
45
+
46
+ ```ruby
47
+ # without nil_chain, we check to make sure the key exists
48
+
49
+ if my_hash.has_key? :foo
50
+ my_hash[:foo].do_stuff
51
+ end
52
+
53
+ # with nil_chain, things look a lot cleaner
54
+
55
+ nil_chain{ my_hash[:foo].do_stuff }
56
+ # => result of my_hash[:foo].do_stuff, or nil
57
+ ```
58
+
59
+ Still pretty simple. Let's try it on a series of connected objects.
60
+
61
+ ```ruby
62
+ class A
63
+ attr_accessor :b
64
+ def initialize(b)
65
+ @b = b
66
+ end
67
+ end
68
+
69
+ class B
70
+ attr_accessor :c
71
+ def initialize(c)
72
+ @c = c
73
+ end
74
+ end
75
+
76
+ class C
77
+ def hello
78
+ "Hello, world!"
79
+ end
80
+ end
81
+
82
+ c = C.new
83
+ b = B.new c
84
+ a = A.new b
85
+
86
+ a.b.c.hello
87
+ # => "Hello, world!"
88
+ ```
89
+
90
+ Let's suppose the presence of attribute `c` is conditional. We must then check for a proper association between objects `b` and `c` before calling `hello`.
91
+
92
+ ```ruby
93
+ b.c = nil
94
+ a.b.c.hello
95
+ # => NoMethodError: undefined method `hello' for nil:NilClass
96
+
97
+ a.b.c.hello unless b.c.nil? || b.c.empty?
98
+ # => nil
99
+
100
+ a.b = nil
101
+
102
+ # Now it's really getting ugly.
103
+ if !a.b.nil? && !a.b.empty?
104
+ a.b.c.hello unless b.c.nil? || b.c.empty?
105
+ end
106
+
107
+ # Imagine if we had a fourth association, or a fifth! The patterns, man!
108
+ ```
109
+
110
+ Or we can just skip all that conditional nonsense.
111
+
112
+ ```ruby
113
+ nil_chain{ a.b.c.hello }
114
+ # => output "Hello, world!" or nil
115
+
116
+ a = nil
117
+ nil_chain{ a.b.c.hello }
118
+ # => still just nil
119
+ ```
120
+
121
+ ##### Examples in Rails
122
+
123
+ We use `nil_chain` all the time in Rails projects. The A-B-C class example above was derived from a frequent use case in our models...
124
+
125
+ ```ruby
126
+ # Model User has ZERO or more addresses, one of which is the primary.
127
+ # Model Address has a zip_code attribute.
128
+
129
+ user = User.find(9876)
130
+ nil_chain{ user.addresses.primary.zip_code }
131
+ # => returns nil if no addresses, or primary not set, otherwise returns zip_code
132
+ ```
133
+
134
+ It also helps when dealing with optional parameters coming in from forms...
135
+
136
+ ```ruby
137
+ # Somewhere in a random rails controller...
138
+
139
+ def search
140
+ case nil_chain { params[:case_state].downcase }
141
+ when 'open' then filter_only_open
142
+ when 'closed' then filter_only_closed
143
+ when 'invalid' then filter_only_invalid
144
+ when 'withdrawn' then filter_only_withdrawn
145
+ when 'canceled' then filter_only_canceled
146
+ end
147
+ # => apply a case state filter, or do nothing
148
+ end
149
+ ```
150
+
151
+ Setting default values on form inputs in views...
152
+
153
+ ```ruby
154
+ select_tag :date_field,
155
+ options_for_select(@dropdown_date_field, nil_chain{params[:date_field]} )
156
+ # => Sets the selected option in the dropdown if the :date_field parameter exists
157
+ ```
158
+
159
+ ##### Custom return value
160
+
161
+ You can change the value that `nil_chain` returns when it catches a `NoMethodError` or `NameError` exception. `nil_chain` accepts a single optional argument before the block to represent the return value. The default is `nil`, but you can set it to whatever you want.
162
+
163
+ We recently used this functionality in generating a CSV report. The client's use case required us to spit out an `'N/A'` string anytime a proper field value was missing. `nil_chain` made the adjustment easy.
164
+
165
+ ```ruby
166
+ CSV.generate do |csv|
167
+ @records.each do |record| # each record represents a single line in the CSV
168
+ values = []
169
+ csv_fields_in_order.each do |field|
170
+ values << nil_chain('N/A') { record.send(field) }
171
+ # respond with a pretty value when the field is empty or invalid
172
+ end
173
+ csv << values
174
+ end
175
+ end
176
+ ```
177
+
178
+ We also find this handy when doing conditional stuff based on presence/absence of a key in a hash.
179
+
180
+ ```ruby
181
+ # without nil_chain
182
+ if my_hash[:foo]
183
+ # (by default, ruby returns nil when you request an unset key)
184
+ var = my_hash[:foo]
185
+ else
186
+ var = :default_value
187
+ end
188
+
189
+ # with nil_chain, we get a nice one liner
190
+
191
+ var = nil_chain(:default_value) { my_hash[:foo] }
192
+
193
+ # What if the default value is coming from somewhere else?
194
+ # What if we want to call a method directly on the hash?
195
+ # What if the ley lines are out of alignment!?
196
+ # No problem.
197
+
198
+ var = nil_chain(Geomancer.reset_ley_lines) { summon_fel_beast[:step_3].scry }
199
+ # => value of summon_fel_beast[:step_3].scry if it's set, or
200
+ # Geomancer.reset_ley_lines if it's not
201
+ ```
202
+
203
+ ##### Aliases
204
+
205
+ `nil_chain` is aliased to `chain` for more brevity, and `method_chain` for alternative clarity.
206
+
207
+
208
+ ---
209
+
210
+ #### `Object#bool_chain`
211
+
212
+ This is the same logic under the hood as `nil_chain`, however we forcibly return a boolean `false` instead of `nil` if the chain breaks.
213
+
214
+ Following our A-B-C example above...
215
+
216
+ ```ruby
217
+ bool_chain{ a.b.c.hello }
218
+ # => false
219
+ ```
220
+
221
+ If you read about `nil_chain`'s custom return value, you know that you can do this explicitly too. This shortcut just saves some typing.
222
+
223
+ ```ruby
224
+ nil_chain(false) { a.b.c.hello }
225
+ # => false
226
+ ```
227
+
228
+ ---
229
+
230
+ #### `Object#same_as`
231
+
232
+ Comparison operator that normalizes both sides into strings, then runs them over `==`.
233
+
234
+ The comparison will work on any class that has a `to_s` method defined on it.
235
+
236
+ ```ruby
237
+ # All these comparisons will return true
238
+
239
+ :foobar.same_as 'foobar'
240
+ 'foobar'.same_as :foobar
241
+ '1'.same_as 1
242
+ 2.same_as '2'
243
+ 3.same_as 3
244
+ ```
245
+
246
+ Normal case-sensitivity rules apply.
247
+
248
+ ```ruby
249
+ :symbol.same_as :SYMBOL
250
+ # => false
251
+
252
+ :symbol.same_as 'SYMBOL'
253
+ # => still false
254
+ ```
255
+
256
+ Since this method is defined in Object, your own custom classes inherit it automatically, allowing you to compare literally anything at any time, without worrying about typecasting!
257
+
258
+ **Make sure you define sane output for `to_s`** and you're all set.
259
+
260
+ We love working with symbols in our code, but symbol values become strings when they hit the database. This meant typecasting wherever new and existing data might collide. No more!
261
+
262
+ ```ruby
263
+ class User
264
+ attr_writer :handle
265
+
266
+ def handle
267
+ @handle || "faceless_one"
268
+ end
269
+
270
+ def to_s
271
+ handle.to_s
272
+ end
273
+ end
274
+
275
+ user = User.new
276
+ :faceless_one.same_as user
277
+ # => true
278
+ user.same_as :faceless_one
279
+ # => true
280
+ user.same_as 'faceless_one'
281
+ # => true
282
+ user.same_as 'FACELESS_ONE'
283
+ # => false
284
+ ```
285
+
286
+ ---
287
+
288
+ #### `Object#class_exists?`
289
+
290
+ > *I just want to know if [insert class name] has been defined!*
291
+ >
292
+ > -- Every dev at some point
293
+
294
+ Sure, Ruby has the `defined?` method, but the output is less than helpful when you're doing conditional flows.
295
+
296
+ ```ruby
297
+ defined?(SuperSaiyan)
298
+ # => nil
299
+
300
+ require 'super_saiyan'
301
+
302
+ defined?(SuperSaiyan)
303
+ # => 'constant'
304
+
305
+ if defined?(SuperSaiyan) == 'constant'
306
+ # Power up to level 4
307
+ # But after that obtuse if-statement, I'm just too tired
308
+ end
309
+ ```
310
+
311
+ `class_exists?` does exactly what you want, and provides an obvious, natural boolean response.
312
+
313
+ ```ruby
314
+ class_exists? :Symbol
315
+ # => true
316
+ class_exists? :Symbology
317
+ # => false, unless you're Dan Brown
318
+ class_exists? :Rails
319
+ # => true in a Rails app
320
+ ```
321
+
322
+ Because the class **might** exist, we cannot pass in the constant version of the name. You **must** use a symbol or string value.
323
+
324
+ ```ruby
325
+ class_exists? DefinitelyFakeClass
326
+ # => NameError: uninitialized constant DefinitelyFakeClass
327
+
328
+ class_exists? :DefinitelyFakeClass
329
+ # => false (at least it better be; if you actually use this name, I will find you...)
330
+ ```
331
+
332
+ ---
333
+
334
+ #### `Object#not_nil?`
335
+
336
+ Because that dangling `!` on the front of a call to `nil?` is just oh so not-ruby-chic.
337
+
338
+ ```ruby
339
+ nil.not_nil?
340
+ # => false
341
+ 'foobar'.not_nil?
342
+ # => true
343
+ ```
344
+
345
+ There, much more legible. Now pass me my fedora and another PBR.
346
+
347
+ ---
348
+
349
+ ### Extensions to `Hash`
350
+
351
+ #### `Hash#delete!`
352
+
353
+ The normal [`Hash#delete`](http://www.ruby-doc.org/core-2.1.5/Hash.html#method-i-delete) method returns the value that's been removed from the hash, but it can be equally useful if we return the newly modified hash instead.
354
+
355
+ This approach effectively throws away the value being deleted, so don't use this when the deleted hash entry is valuable.
356
+
357
+ ```ruby
358
+ power_rangers = {
359
+ :red => 'Jason Scott',
360
+ :blue => 'Billy Cranston',
361
+ :green => 'Tommy Oliver'
362
+ }
363
+
364
+ power_rangers.delete! :green
365
+ # => { :red => 'Jason Lee Scott', :blue => 'Billy Cranston' }
366
+ ```
367
+
368
+ If the key is not found, the hash is returned unaltered.
369
+
370
+ ```ruby
371
+ power_rangers.delete! :radiant_orchid
372
+ # => { :red => 'Jason Lee Scott', :blue => 'Billy Cranston' }
373
+ # It probably would've triggered if I included Kimberly
374
+ ```
375
+
376
+ ---
377
+
378
+ #### `Hash#delete_each`
379
+ Deletes all records in a hash matching the keys passed in as an array. Returns a hash of deleted entries. Silently ignores any keys which are not found.
380
+
381
+ ```ruby
382
+ mega_man_bosses = { :metal_man => 1, :bubble_man => 2, :heat_man => 3, :wood_man => 4 }
383
+
384
+ mega_man_bosses.delete_each :chill_penguin, :spark_mandrill
385
+ # => nil, and get your series straight
386
+ mega_man_bosses
387
+ # => { :metal_man => 1, :bubble_man => 2, :heat_man => 3, :wood_man => 4 }
388
+
389
+ mega_man_bosses.delete_each :metal_man
390
+ # => { :metal_man => 1 }
391
+ mega_man_bosses
392
+ # => { :bubble_man => 2, :heat_man => 3, :wood_man => 4 }
393
+
394
+ mega_man_bosses.delete_each :bubble_man, :heat_man, :wheel_gator
395
+ # => { :bubble_man => 2, :heat_man => 3 }
396
+ mega_man_bosses
397
+ # => { :wood_man => 4 }
398
+ ```
399
+
400
+ ---
401
+
402
+ #### `Hash#delete_each!`
403
+
404
+ Same logic as `delete_each`, but return the modified hash, and discard the deleted values.
405
+
406
+ Maintains parity with the contrast of `delete` vs `delete!` described above.
407
+
408
+ ```ruby
409
+ mega_man_bosses = { :air_man => 5, :crash_man => 6, :flash_man => 7, :quick_man => 8 }
410
+
411
+ mega_man_bosses.delete_each! :yellow_devil, :air_man
412
+ # => { :crash_man => 6, :flash_man => 7, :quick_man => 8 }
413
+
414
+ mega_man_bosses.delete_each! :flash_man
415
+ # => { :crash_man => 6, :quick_man => 8 }
416
+ # Take out flash anytime after metal, I like to wait until I need a breather.
417
+
418
+ mega_man_bosses.delete_each! :crash_man, :quick_man
419
+ # => { }
420
+ ```
421
+
422
+ ---
423
+
424
+ ### `Fixnum#length` and `Bignum#length`
425
+
426
+ Ruby doesn't provide a native way to see how many digits are in an integer, but that's exactly what we worry about anytime out database `INT` lengths collide with Ruby `Fixnum` or `Bignum` values.
427
+
428
+ ```ruby
429
+ 1.length
430
+ # => 1
431
+ 9.length
432
+ # => 1
433
+ 90.length
434
+ # => 2
435
+ 900.length
436
+ # => 3
437
+ 9000.length
438
+ # => 4
439
+ 9001.length
440
+ # => OVER NINE THOUSAAAAAAND (also 4)
441
+
442
+ 12356469787881584554556.class.name
443
+ # => "Bignum"
444
+ 12356469787881584554556.length
445
+ # => 23
446
+ ```
447
+
448
+ For consistency, we added matching methods to `Float` and `BigDecimal` that simply raise an `ArgumentError`.
449
+
450
+ ```ruby
451
+ 12356469.987.class.name
452
+ # => "Float"
453
+ 12356469.987.length
454
+ # => ArgumentError: Cannot get length: "12356469.987" is not an integer
455
+
456
+ 1265437718438866624512.123.class.name
457
+ # => "Float" (it's really BigDecimal, trust us)
458
+ 1265437718438866624512.123.length
459
+ # => ArgumentError: Cannot get length: "1.2654377184388666e+21" is not an integer
460
+ ```
461
+
462
+ ---
463
+
464
+ ### Typecasting *to* `Boolean`
465
+
466
+ Boolean values are frequently represented as strings and integers in databases and file storage. So we always thought it was a little odd that Ruby lacked a boolean typecasting method, given the proliferation of `to_*` methods for `String`, `Symbol`, `Integer`, `Float`, `Hash`, etc.
467
+
468
+ So we made one for strings and integers.
469
+
470
+ #### `String#to_bool`
471
+
472
+ Strings get analyzed and return true/false for a small set of potential values. These comparisons are case-insensitive.
473
+
474
+ ```ruby
475
+ ['1', 't', 'true', 'on', 'y', 'yes'].each do |true_string|
476
+ true_string.to_bool
477
+ # => true
478
+
479
+ true_string.upcase.to_bool
480
+ # => true
481
+ end
482
+
483
+ ['0', 'f', 'false', 'off', 'n', 'no'].each do |false_string|
484
+ false_string.to_bool
485
+ # => false
486
+
487
+ false_string.upcase.to_bool
488
+ # => false
489
+ end
490
+
491
+ # empty strings and strings with only spaces evaluate to false
492
+ ["", " ", " ", " "].each do |empty_string|
493
+ empty_string.to_bool
494
+ # => false
495
+ end
496
+ ```
497
+
498
+ A string with anything other than these matching values will throw an error.
499
+
500
+ ```ruby
501
+ ["foo", "tru", "trueish", "druish", "000"].each do |bad_string|
502
+ bad_string.to_bool
503
+ # => ArgumentError: invalid value for Boolean
504
+ end
505
+ ```
506
+
507
+ #### `Fixnum#to_bool`
508
+
509
+ A zero is false, a one is true. That's it. Everything else throws `ArgumentError`
510
+
511
+ ```ruby
512
+ 0.to_bool
513
+ # => false
514
+
515
+ 1.to_bool
516
+ # => true
517
+
518
+ 2.to_bool
519
+ # => ArgumentError: invalid value for Boolean: "2"
520
+
521
+ -1.to_bool
522
+ # => ArgumentError: invalid value for Boolean: "-1"
523
+
524
+ 8675309.to_bool
525
+ # => ArgumentError: invalid value for Boolean: "8675309"
526
+ ```
527
+
528
+ #### `NilClass#to_bool`
529
+
530
+ A nil value typecasted to a boolean is false.
531
+
532
+ ```ruby
533
+ nil == false
534
+ # => false
535
+
536
+ nil.to_bool
537
+ # => false
538
+
539
+ nil.to_bool == false
540
+ # => true
541
+ ```
542
+
543
+ #### `TrueClass#to_bool` and `FalseClass#to_bool`
544
+
545
+ They return what you expect, we added them simply for sake of consistency, in case your code calls `to_bool` on a variable of indeterminate type.
546
+
547
+ ```ruby
548
+ true.to_bool
549
+ # => true
550
+
551
+ false.to_bool
552
+ # => false
553
+ ```
554
+
555
+ ---
556
+
557
+ ### Typecasting *from* `Boolean` and `Nil`
558
+
559
+ Complementing the methods to typecast boolean values coming out of data storage, we have methods to convert booleans and `nil` into string and symbol representations.
560
+
561
+ ```ruby
562
+ true.to_i
563
+ # => 1
564
+ true.to_sym
565
+ # => :true
566
+
567
+ false.to_i
568
+ # => 0
569
+ false.to_sym
570
+ # => :false
571
+
572
+ nil.to_i
573
+ # => 0 (follows same logic as `NilClass#to_bool`)
574
+ nil.to_sym
575
+ # => :nil
576
+ ```
577
+
578
+ ## Share your finishing moves!
579
+
580
+ ### Got an idea for another finisher?
581
+
582
+ 1. Fork this repo
583
+ 2. Write your tests
584
+ 3. Add your finisher
585
+ 4. Repeat steps 2 and 3 until badass
586
+ 5. Submit a pull request
587
+ 6. Everyone kicks even more ass!
588
+
589
+ ###### Got a good nerdy reference for our code samples?
590
+ We'll take pull requests on those too. Bonus karma points if you apply the reference to the specs too.
591
+
592
+ ## License
593
+
594
+ Finishing Moves is distributed under MIT license.
595
+
596
+ Copyright (c) 2015 Forge Software, LLC
597
+
598
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
599
+
600
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
601
+
602
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.