destruct 0.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8896e1df8a68ecfa8b0b885bd83e5854bfd5347b
4
+ data.tar.gz: a836c4d9a1029115f22dac0e02416eb1f3e17151
5
+ SHA512:
6
+ metadata.gz: 8bd49a04bb17c0c8552351a16cfe6e89496d29d88a1f049b7c4e4c77a8462957bbee426d762d356e87f8efad9b0dfc0188e15f10a967d14398886a946e806214
7
+ data.tar.gz: 1c1641c038067cf4b25c7157f7e7d2b575b868b641fb7e6822e22ae5192513efa5c52fa7f6158f5748f6accb8da37b884ac493566ed42f521a77c2f11744cab6
@@ -0,0 +1,9 @@
1
+ steps:
2
+ - name: ":rubocop:"
3
+ command: bin/rubocop
4
+ timeout_in_minutes: 30
5
+
6
+ - name: ":rspec:"
7
+ command: bin/test
8
+ timeout_in_minutes: 30
9
+ artifact_paths: cache.tar.lz4
@@ -0,0 +1,3 @@
1
+ coverage
2
+ pkg
3
+ rdoc
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --require spec_helper
@@ -0,0 +1,2 @@
1
+ FROM lendinghome/rails
2
+ MAINTAINER github@lendinghome.com
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://www.rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "codeclimate-test-reporter"
6
+ gem "rspec"
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ destruct (0.0.0)
5
+
6
+ GEM
7
+ remote: https://www.rubygems.org/
8
+ specs:
9
+ codeclimate-test-reporter (0.6.0)
10
+ simplecov (>= 0.7.1, < 1.0.0)
11
+ diff-lcs (1.2.5)
12
+ docile (1.1.5)
13
+ json (2.0.2)
14
+ rspec (3.5.0)
15
+ rspec-core (~> 3.5.0)
16
+ rspec-expectations (~> 3.5.0)
17
+ rspec-mocks (~> 3.5.0)
18
+ rspec-core (3.5.4)
19
+ rspec-support (~> 3.5.0)
20
+ rspec-expectations (3.5.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.5.0)
23
+ rspec-mocks (3.5.0)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.5.0)
26
+ rspec-support (3.5.0)
27
+ simplecov (0.12.0)
28
+ docile (~> 1.1.0)
29
+ json (>= 1.8, < 3)
30
+ simplecov-html (~> 0.10.0)
31
+ simplecov-html (0.10.0)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ codeclimate-test-reporter
38
+ destruct!
39
+ rspec
40
+
41
+ BUNDLED WITH
42
+ 1.13.5
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 LendingHome - github@lendinghome.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,683 @@
1
+ # ![LendingHome](https://cloud.githubusercontent.com/assets/2419/19467866/7efa93a8-94c8-11e6-93e7-4375dbb8a7bc.png) destruct
2
+ [![Code Climate](https://codeclimate.com/github/LendingHome/destruct/badges/gpa.svg)](https://codeclimate.com/github/LendingHome/destruct) [![Coverage](https://codeclimate.com/github/LendingHome/destruct/badges/coverage.svg)](https://codeclimate.com/github/LendingHome/destruct) [![Gem Version](https://badge.fury.io/rb/destruct.svg)](http://badge.fury.io/rb/destruct)
3
+
4
+ > ES6 style object destructuring in Ruby
5
+
6
+ Check out the JavaScript [ES6 object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) documentation for more information.
7
+
8
+ ## Why?
9
+
10
+ This was **primarily a learning exercise** to understand how this newer ES6 feature could work under the hood. We're not currently using this in production anywhere but it was a pretty fun challenge to solve.
11
+
12
+ ---
13
+
14
+ Ruby 2.3+ already has some built-in methods and operators for simple object destructuring:
15
+
16
+ * [`Array#dig`](http://ruby-doc.org/core-2.3.0/Array.html#method-i-dig)
17
+ * [`Hash#dig`](http://ruby-doc.org/core-2.3.0/Hash.html#method-i-dig)
18
+ * [`Struct#dig`](https://ruby-doc.org/core-2.3.0/Struct.html#method-i-dig)
19
+ * [`Array#values_at`](https://ruby-doc.org/core-2.3.0/Array.html#method-i-values_at)
20
+ * [`Hash#values_at`](https://ruby-doc.org/core-2.3.0/Hash.html#method-i-values_at)
21
+ * [Splat operator `*`](https://ruby-doc.org/core-2.3.0/doc/syntax/calling_methods_rdoc.html#label-Array+to+Arguments+Conversion)
22
+ * [Safe navigation operator `&.`](https://bugs.ruby-lang.org/issues/11537)
23
+
24
+ This gem introduces a couple of new methods to the `Object` class for more complex destructuring.
25
+
26
+ * `Object#dig`
27
+ * `Object#destruct`
28
+
29
+ It's mostly **useful for fetching multiple nested values out of objects** in a single method call.
30
+
31
+ ## Installation
32
+
33
+ Add this gem to the project `Gemfile`.
34
+
35
+ ```ruby
36
+ gem "destruct"
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ### `Object#dig`
42
+
43
+ This behaves just like the `dig` methods in `Array`, `Hash`, and `Struct` allowing ALL objects to be destructured.
44
+
45
+ The implementation simply uses `send` to pass valid method calls thru to objects recursively.
46
+
47
+ ```ruby
48
+ class Object
49
+ def dig(method, *paths)
50
+ object = send(method) if respond_to?(method)
51
+ paths.any? ? object&.dig(*paths) : object
52
+ end
53
+ end
54
+ ```
55
+
56
+ This method behaves very similar to the safe navigation operator `&.` but checks if the object responds to the method before attempting to call it. Invalid method calls return `nil` instead of raising `NoMethodError`.
57
+
58
+ ```ruby
59
+ "test".dig(:upcase, :reverse) # "TSET"
60
+ "test".dig(:invalid, :chain, :of, :methods) # nil
61
+ ```
62
+
63
+ It also delegates to native `dig` implementations for `Array`, `Hash`, or `Struct` objects whenever possible.
64
+
65
+ ```ruby
66
+ class Blog
67
+ def posts
68
+ [
69
+ { "title" => "Testing" },
70
+ { "title" => "Example" }
71
+ ]
72
+ end
73
+ end
74
+
75
+ Blog.new.dig(:posts, 1, "title") # "Example"
76
+ ```
77
+
78
+ ### `Object#destruct`
79
+
80
+ This method is like a hybrid of all the other native Ruby destructuring methods! Let's define an example object:
81
+
82
+ ```ruby
83
+ object = {
84
+ id: 123,
85
+ title: "Hi",
86
+ translations: [
87
+ {
88
+ locale: "es_MX",
89
+ last_edit: "2014-04-14T08:43:37",
90
+ title: "Hola"
91
+ }
92
+ ],
93
+ url: "/hi-123"
94
+ }
95
+ ```
96
+
97
+ It behaves like `values_at` and looks up values by keys:
98
+
99
+ ```ruby
100
+ id, url = object.destruct(:id, :url)
101
+ puts id # 123
102
+ puts url # "/hi-123"
103
+ ```
104
+
105
+ It behaves like `dig` to lookup nested values:
106
+
107
+ ```ruby
108
+ title, locale_title = object.destruct(:title, [:translations, 0, :title])
109
+ puts title # "Hi"
110
+ puts locale_title # "Hola"
111
+ ```
112
+
113
+ It accepts hashes to `dig` out nested values as well:
114
+
115
+ ```ruby
116
+ locale, title = object.destruct(translations: { 0 => [:locale, :title] })
117
+ puts locale # "es_MX"
118
+ puts title # "Hola"
119
+ ```
120
+
121
+ It accepts a mixture of different argument types:
122
+
123
+ ```ruby
124
+ title, last_edit, locale, locale_title = object.destruct(
125
+ :title,
126
+ [:translations, 0, :last_edit],
127
+ translations: { 0 => [:locale, :title] }
128
+ )
129
+
130
+ puts title # "Hi"
131
+ puts last_edit # "2014-04-14T08:43:37"
132
+ puts locale # "es_MX"
133
+ puts locale_title # "Hola"
134
+ ```
135
+
136
+ It accepts a block to lookup nested values with a clear and convenient DSL:
137
+
138
+ ```ruby
139
+ title, last_edit, locale, url = object.destruct do
140
+ title
141
+ translations[0].last_edit
142
+ translations[0][:locale]
143
+ url
144
+ end
145
+
146
+ puts title # "Hi"
147
+ puts last_edit # "2014-04-14T08:43:37"
148
+ puts locale # "es_MX"
149
+ puts url # "/hi-123"
150
+ ```
151
+
152
+ It returns a `Destruct::Hash` object when the return values are not splatted:
153
+
154
+ ```ruby
155
+ destructured = object.destruct do
156
+ title
157
+ translations[0].last_edit
158
+ translations[0][:locale]
159
+ url
160
+ end
161
+
162
+ puts destructured.title # "Hi"
163
+ puts destructured[:title] # "Hi"
164
+ puts destructured[0] # "Hi"
165
+
166
+ puts destructured.last_edit # "2014-04-14T08:43:37"
167
+ puts destructured.locale # "es_MX"
168
+
169
+ puts destructured.url # "/hi-123"
170
+ puts destructured[-1] # "/hi-123"
171
+
172
+ puts destructured[999] # nil
173
+ puts destructured[:missing] # nil
174
+ puts destructured.missing # NoMethodError
175
+ ```
176
+
177
+ Note that `Destruct::Hash` values are overwritten if there are multiple with the same keys:
178
+
179
+ ```ruby
180
+ destructured = object.destruct(:title, [:translations, 0, :title])
181
+
182
+ puts destructured.title # "Hola"
183
+
184
+ # This is where the index lookups really come in handy
185
+ puts destructured[0] # "Hi"
186
+ puts destructured[1] # "Hola"
187
+ ```
188
+
189
+ The return value destructuring is done using `Destruct::Hash#to_ary` for implicit `Array` conversion!
190
+
191
+ ## Examples
192
+
193
+ Let's compare some of the JavaScript [ES6 destructuring examples](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) with their Ruby equivalents.
194
+
195
+ Note that almost all of these examples simply use native Ruby 2.3+ features!
196
+
197
+ ### Array destructuring
198
+
199
+ #### Basic variable assignment
200
+
201
+ ```javascript
202
+ var foo = ["one", "two", "three"];
203
+ var [one, two, three] = foo;
204
+
205
+ console.log(one); // "one"
206
+ console.log(two); // "two"
207
+ console.log(three); // "three"
208
+ ```
209
+
210
+ ```ruby
211
+ foo = ["one", "two", "three"]
212
+ one, two, three = foo
213
+
214
+ puts one # "one"
215
+ puts two # "two"
216
+ puts three # "three"
217
+ ```
218
+
219
+ #### Default values
220
+
221
+ ```javascript
222
+ var [a=5, b=7] = [1];
223
+
224
+ console.log(a); // 1
225
+ console.log(b); // 7
226
+ ```
227
+
228
+ ```ruby
229
+ a, b = [1]
230
+ a ||= 5
231
+ b ||= 7
232
+
233
+ puts a # 1
234
+ puts b # 7
235
+ ```
236
+
237
+ #### Swapping variables
238
+
239
+ ```javascript
240
+ var a = 1;
241
+ var b = 3;
242
+ [a, b] = [b, a];
243
+
244
+ console.log(a); // 3
245
+ console.log(b); // 1
246
+ ```
247
+
248
+ ```ruby
249
+ a = 1
250
+ b = 3
251
+ a, b = b, a
252
+
253
+ puts a # 3
254
+ puts b # 1
255
+ ```
256
+
257
+ #### Parsing an array returned from a function
258
+
259
+ ```javascript
260
+ function f() {
261
+ return [1, 2];
262
+ }
263
+
264
+ var [a, b] = f();
265
+
266
+ console.log(a); // 1
267
+ console.log(b); // 2
268
+ ```
269
+
270
+ ```ruby
271
+ def f
272
+ [1, 2]
273
+ end
274
+
275
+ a, b = f
276
+
277
+ puts a # 1
278
+ puts b # 2
279
+ ```
280
+
281
+ #### Ignoring some returned values
282
+
283
+ ```javascript
284
+ function f() {
285
+ return [1, 2, 3];
286
+ }
287
+
288
+ var [a, , b] = f();
289
+
290
+ console.log(a); // 1
291
+ console.log(b); // 3
292
+ ```
293
+
294
+ ```ruby
295
+ def f
296
+ [1, 2, 3]
297
+ end
298
+
299
+ a, _, b = f
300
+
301
+ puts a # 1
302
+ puts b # 3
303
+ ```
304
+
305
+ #### Ignoring remaining values
306
+
307
+ ```javascript
308
+ var [a, b] = [1, 2, 3, 4];
309
+
310
+ console.log(a); // 1
311
+ console.log(b); // 2
312
+ ```
313
+
314
+ ```ruby
315
+ a, b = [1, 2, 3, 4]
316
+
317
+ puts a # 1
318
+ puts b # 2
319
+ ```
320
+
321
+ #### Capture remaining values
322
+
323
+ ```javascript
324
+ var [a, b, ...c] = [1, 2, 3, 4];
325
+
326
+ console.log(c); // [3, 4]
327
+ ```
328
+
329
+ ```ruby
330
+ a, b, *c = [1, 2, 3, 4]
331
+
332
+ puts c.inspect # [3, 4]
333
+ ```
334
+
335
+ #### Destructure a nested array
336
+
337
+ ```javascript
338
+ const avengers = [
339
+ "Natasha Romanoff",
340
+ ["Tony Stark", "James Rhodes"],
341
+ ["Steve Rogers", "Sam Wilson"]
342
+ ];
343
+
344
+ const [blackWidow, [ironMan, warMachine], [cap, falcon]] = avengers;
345
+
346
+ console.log(warMachine); // "James Rhodes"
347
+ ```
348
+
349
+ ```ruby
350
+ avengers = [
351
+ "Natasha Romanoff",
352
+ ["Tony Stark", "James Rhodes"],
353
+ ["Steve Rogers", "Sam Wilson"]
354
+ ]
355
+
356
+ black_widow, iron_man, war_machine, cap, falcon = avengers.flatten
357
+
358
+ puts war_machine # "James Rhodes"
359
+ ```
360
+
361
+ #### Pluck a single value from a deeply nested array
362
+
363
+ ```javascript
364
+ const avengers = [
365
+ "Natasha Romanoff",
366
+ [["Tony Stark", "Pepper Potts"], "James Rhodes"],
367
+ ["Steve Rogers", "Sam Wilson"]
368
+ ];
369
+
370
+ const [, [[, potts ]]] = avengers;
371
+
372
+ console.log(potts); // "Pepper Potts"
373
+ ```
374
+
375
+ ```ruby
376
+ avengers = [
377
+ "Natasha Romanoff",
378
+ [["Tony Stark", "Pepper Potts"], "James Rhodes"],
379
+ ["Steve Rogers", "Sam Wilson"]
380
+ ]
381
+
382
+ potts = avengers.dig(1, 0, 1)
383
+
384
+ puts potts # "Pepper Potts"
385
+ ```
386
+
387
+ #### Pulling values from a regular expression match
388
+
389
+ ```javascript
390
+ var url = "https://developer.mozilla.org/en-US/Web/JavaScript";
391
+
392
+ var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
393
+ console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]
394
+
395
+ var [, protocol, fullhost, fullpath] = parsedURL;
396
+ console.log(protocol); // "https"
397
+ ```
398
+
399
+ ```ruby
400
+ url = "https://developer.mozilla.org/en-US/Web/JavaScript"
401
+
402
+ parsed_url = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.match(url).to_a
403
+ puts parsed_url.inspect # ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]
404
+
405
+ _, protocol, fullhost, fullpath = parsed_url.to_a
406
+ puts protocol # "https"
407
+ ```
408
+
409
+ ### Object destructuring
410
+
411
+ #### Basic assignment
412
+
413
+ ```javascript
414
+ var o = {p: 42, q: true};
415
+ var {p, q} = o;
416
+
417
+ console.log(p); // 42
418
+ console.log(q); // true
419
+ ```
420
+
421
+ ```ruby
422
+ o = { p: 42, q: true }
423
+ p, q = o.values_at(:p, :q)
424
+
425
+ puts p # 42
426
+ puts q # true
427
+ ```
428
+
429
+ #### Assigning to new variable names
430
+
431
+ ```javascript
432
+ var o = {p: 42, q: true};
433
+ var {p: foo, q: bar} = o;
434
+
435
+ console.log(foo); // 42
436
+ console.log(bar); // true
437
+ ```
438
+
439
+ ```ruby
440
+ o = { p: 42, q: true }
441
+ foo, bar = o.values_at(:p, :q)
442
+
443
+ puts foo # 42
444
+ puts bar # true
445
+ ```
446
+
447
+ #### Default values
448
+
449
+ ```javascript
450
+ var {a=10, b=5} = {a: 3};
451
+
452
+ console.log(a); // 3
453
+ console.log(b); // 5
454
+ ```
455
+
456
+ ```ruby
457
+ a, b = { a: 3 }.values_at(:a, :b)
458
+ a ||= 10
459
+ b ||= 5
460
+
461
+ puts a # 3
462
+ puts b # 5
463
+ ```
464
+
465
+ #### Setting default function parameters
466
+
467
+ ```javascript
468
+ function drawES6Chart({size = "big", cords = { x: 0, y: 0 }, radius = 25} = {}) {
469
+ console.log(size, cords, radius);
470
+ // do some chart drawing
471
+ }
472
+
473
+ drawES6Chart({
474
+ cords: { x: 18, y: 30 },
475
+ radius: 30
476
+ });
477
+ ```
478
+
479
+ ```ruby
480
+ def draw_es6_chart(size: "big", cords: { x: 0, y: 0 }, radius: 25)
481
+ puts size, cords, radius
482
+ # do some chart drawing
483
+ end
484
+
485
+ draw_es6_chart(
486
+ cords: { x: 18, y: 30 },
487
+ radius: 30
488
+ )
489
+ ```
490
+
491
+ #### Nested object and array destructuring
492
+
493
+ ```javascript
494
+ var metadata = {
495
+ title: "Scratchpad",
496
+ translations: [
497
+ {
498
+ locale: "de",
499
+ localization_tags: [ ],
500
+ last_edit: "2014-04-14T08:43:37",
501
+ url: "/de/docs/Tools/Scratchpad",
502
+ title: "JavaScript-Umgebung"
503
+ }
504
+ ],
505
+ url: "/en-US/docs/Tools/Scratchpad"
506
+ };
507
+
508
+ var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;
509
+
510
+ console.log(englishTitle); // "Scratchpad"
511
+ console.log(localeTitle); // "JavaScript-Umgebung"
512
+ ```
513
+
514
+ ```ruby
515
+ metadata = {
516
+ title: "Scratchpad",
517
+ translations: [
518
+ {
519
+ locale: "de",
520
+ localization_tags: [ ],
521
+ last_edit: "2014-04-14T08:43:37",
522
+ url: "/de/docs/Tools/Scratchpad",
523
+ title: "JavaScript-Umgebung"
524
+ }
525
+ ],
526
+ url: "/en-US/docs/Tools/Scratchpad"
527
+ }
528
+
529
+ english_title, locale_title = metadata.destruct do
530
+ title
531
+ translations[0].title
532
+ end
533
+
534
+ puts english_title # "Scratchpad"
535
+ puts locale_title # "JavaScript-Umgebung"
536
+ ```
537
+
538
+ #### For of iteration and destructuring
539
+
540
+ ```javascript
541
+ var people = [
542
+ {
543
+ name: "Mike Smith",
544
+ family: {
545
+ mother: "Jane Smith",
546
+ father: "Harry Smith",
547
+ sister: "Samantha Smith"
548
+ },
549
+ age: 35
550
+ },
551
+ {
552
+ name: "Tom Jones",
553
+ family: {
554
+ mother: "Norah Jones",
555
+ father: "Richard Jones",
556
+ brother: "Howard Jones"
557
+ },
558
+ age: 25
559
+ }
560
+ ];
561
+
562
+ for (var {name: n, family: { father: f } } of people) {
563
+ console.log("Name: " + n + ", Father: " + f);
564
+ }
565
+
566
+ // "Name: Mike Smith, Father: Harry Smith"
567
+ // "Name: Tom Jones, Father: Richard Jones"
568
+ ```
569
+
570
+ ```ruby
571
+ people = [
572
+ {
573
+ name: "Mike Smith",
574
+ family: {
575
+ mother: "Jane Smith",
576
+ father: "Harry Smith",
577
+ sister: "Samantha Smith"
578
+ },
579
+ age: 35
580
+ },
581
+ {
582
+ name: "Tom Jones",
583
+ family: {
584
+ mother: "Norah Jones",
585
+ father: "Richard Jones",
586
+ brother: "Howard Jones"
587
+ },
588
+ age: 25
589
+ }
590
+ ]
591
+
592
+ people.each do |person|
593
+ n, f = person.destruct(:name, family: :father)
594
+ puts "Name: #{n}, Father: #{f}"
595
+ end
596
+
597
+ # "Name: Mike Smith, Father: Harry Smith"
598
+ # "Name: Tom Jones, Father: Richard Jones"
599
+ ```
600
+
601
+ #### Pulling fields from objects passed as function parameter
602
+
603
+ ```javascript
604
+ function userId({id}) {
605
+ return id;
606
+ }
607
+
608
+ function whois({displayName: displayName, fullName: {firstName: name}}){
609
+ console.log(displayName + " is " + name);
610
+ }
611
+
612
+ var user = {
613
+ id: 42,
614
+ displayName: "jdoe",
615
+ fullName: {
616
+ firstName: "John",
617
+ lastName: "Doe"
618
+ }
619
+ };
620
+
621
+ console.log("userId: " + userId(user)); // "userId: 42"
622
+ whois(user); // "jdoe is John"
623
+ ```
624
+
625
+ ```ruby
626
+ def user_id(id:)
627
+ id
628
+ end
629
+
630
+ def whois(display_name:, full_name:)
631
+ puts "#{display_name} is #{full_name[:first_name]}"
632
+ end
633
+
634
+ user = {
635
+ id: 42,
636
+ displayName: "jdoe",
637
+ fullName: {
638
+ firstName: "John",
639
+ lastName: "Doe"
640
+ }
641
+ }
642
+
643
+ puts "userId: #{user_id(user)}" # "userId: 42"
644
+ whois(user) # "jdoe is John"
645
+ ```
646
+
647
+ #### Computed object property names
648
+
649
+ ```javascript
650
+ let key = "z";
651
+ let { [key]: foo } = { z: "bar" };
652
+
653
+ console.log(foo); // "bar"
654
+ ```
655
+
656
+ ```ruby
657
+ key = :z
658
+ foo = { z: "bar" }[key]
659
+
660
+ puts foo # "bar"
661
+ ```
662
+
663
+ ## Testing
664
+
665
+ ```bash
666
+ bundle exec rspec
667
+ ```
668
+
669
+ ## Contributing
670
+
671
+ * Fork the project.
672
+ * Make your feature addition or bug fix.
673
+ * Add tests for it. This is important so we don't break it in a future version unintentionally.
674
+ * Commit, do not mess with the version or history.
675
+ * Open a pull request. Bonus points for topic branches.
676
+
677
+ ## Authors
678
+
679
+ * [Sean Huber](https://github.com/shuber)
680
+
681
+ ## License
682
+
683
+ [MIT](https://github.com/lendinghome/destruct/blob/master/LICENSE) - Copyright © 2016 LendingHome