-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1752 lines (1154 loc) · 115 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Daniel Chang</title>
<meta name="author" content="Daniel Chang">
<meta name="description" content="Ever get tired of typing the same commands over and over? Try adding these aliases to your .bash_profile and then never look back. 1. dbreloadall 1 …">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link href="" rel="alternate" title="Daniel Chang" type="application/atom+xml">
<link rel="canonical" href="">
<link href="/favicon.png" rel="shortcut icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<script async="true" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>
<header id="header" class="inner"><h1><a href="/">Daniel Chang</a></h1>
<nav id="main-nav"><ul class="main">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</nav>
<nav id="mobile-nav">
<div class="alignleft menu">
<a class="button">Menu</a>
<div class="container"><ul class="main">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</div>
</div>
<div class="alignright search">
<a class="button"></a>
<div class="container">
<form action="http://google.com/search" method="get">
<input type="text" name="q" results="0">
<input type="hidden" name="q" value="site:danielchangNYC.github.io">
</form>
</div>
</div>
</nav>
<nav id="sub-nav" class="alignright">
<div class="social">
<a class="google" href="https://plus.google.com/117389635991723583799?rel=author" title="Google+">Google+</a>
<a class="twitter" href="http://twitter.com/danielchangNYC" title="Twitter">Twitter</a>
<a class="github" href="https://github.com/danielchangNYC" title="GitHub">GitHub</a>
</div>
<form class="search" action="http://google.com/search" method="get">
<input class="alignright" type="text" name="q" results="0">
<input type="hidden" name="q" value="site:danielchangNYC.github.io">
</form>
</nav>
</header>
<div id="content" class="inner">
<article class="post">
<h2 class="title">
<a href="/blog/2014/05/15/two-bash-profile-aliases/">
Two Nifty Bash Profile Aliases</a>
</h2>
<div class="entry-content">
<p>Ever get tired of typing the same commands over and over? Try adding these aliases to your <code>.bash_profile</code> and then never look back.</p>
<h2>1. dbreloadall</h2>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>alias dbreloadall="rake db:migrate:reset && rake db:migrate:reset RAILS_ENV=test && rake db:seed && rake db:seed RAILS_ENV=test"</span></code></pre></td></tr></table></div></figure>
<p>Reset (drop, create, then migrate) then seed.</p>
<p>Should’ve called this dbnuke. Or dbregen. Or dbreincarnate. Or dbdeebee (personal fav). Name it whatever you’d like.</p>
<h2>2. schemareload</h2>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>alias schemareload="rm db/schema.rb && rake db:migrate"</span></code></pre></td></tr></table></div></figure>
<p>Use this when you’re doing a git rebase and there’s a schema conflict.</p>
</div>
<div class="meta">
<div class="date">
<time datetime="2014-05-15T22:45:00-04:00" pubdate data-updated="true">May 15<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/bash/'>bash</a>, <a class='category' href='/blog/categories/command-line/'>command-line</a>, <a class='category' href='/blog/categories/git/'>git</a>, <a class='category' href='/blog/categories/rails/'>rails</a>, <a class='category' href='/blog/categories/ruby/'>ruby</a>, <a class='category' href='/blog/categories/shell/'>shell</a>, <a class='category' href='/blog/categories/workflow/'>workflow</a>
</div>
<div class="comments"><a href="/blog/2014/05/15/two-bash-profile-aliases/#disqus_thread">Comments</a></div>
</div>
</article>
<article class="post">
<h2 class="title">
<a href="/blog/2014/04/24/ruby-array-set-intersection/">
Ruby Array Set Intersection: A Rails Use-Case and Algorithm Analysis in C</a>
</h2>
<div class="entry-content">
<p>Here’s some smelly code I wrote for the <a href="http://prework.flatironschool.com/">Flatiron School pre-work</a> progress-tracker app.</p>
<h1>Brittle Methods</h1>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Progress</span> <span class="o"><</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span>
</span><span class='line'> <span class="n">belongs_to</span> <span class="ss">:topic</span>
</span><span class='line'> <span class="n">serialize</span> <span class="ss">:completed_lessons</span><span class="p">,</span> <span class="nb">Array</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">topic_complete?</span>
</span><span class='line'> <span class="n">topic</span><span class="o">.</span><span class="n">total_lessons</span> <span class="o">==</span> <span class="n">completed_lessons</span><span class="o">.</span><span class="n">length</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Topic</span> <span class="o"><</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span>
</span><span class='line'> <span class="n">has_many</span> <span class="ss">:progresses</span>
</span><span class='line'> <span class="n">serialize</span> <span class="ss">:lesson_order</span><span class="p">,</span> <span class="nb">Array</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">add_lesson</span><span class="p">(</span><span class="n">lesson</span><span class="p">)</span>
</span><span class='line'> <span class="n">lesson_order</span> <span class="o"><<</span> <span class="n">lesson</span><span class="o">.</span><span class="n">id</span>
</span><span class='line'> <span class="n">total_lessons</span> <span class="o">+=</span> <span class="mi">1</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>add_lesson</code> is brittle. A new coder on this project has to know to add lessons using this method; the design is therefore NOT transparent. There is also a duplication of data: calling <code>lesson_order.length</code> gives you the total number of lessons, making a <code>total_lessons</code> attribute a violation of the DRY principle. It should be a method instead.</p>
<p><code>topic_complete?</code> also felt prone to false positives and negatives. If an admin replaces a lesson, is a completed progress still complete? What about if a lesson is removed? Our method would return false.</p>
<p><strong>I needed a way to actually compare what was in <code>completed_lessons</code> and <code>lesson_order</code>.</strong></p>
<h1>Set Theory in Full Motion</h1>
<p>Set theory review: The intersection of two sets is the set of all common elements. Ruby’s Array class has such a method which can be used like an operator: <code>&</code>.</p>
<p>The <a href="http://www.ruby-doc.org/core-2.1.1/Array.html#method-i-26">& operator</a> is called the set intersection operator.</p>
<figure class='code'><figcaption><span>how-&-works</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">[</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span> <span class="o">]</span> <span class="o">&</span> <span class="o">[</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="o">]</span> <span class="c1">#=> [ 1, 3 ]</span>
</span></code></pre></td></tr></table></div></figure>
<h2>Failed Solution, Learned Lesson</h2>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">topic_complete?</span>
</span><span class='line'> <span class="n">completed_lessons</span> <span class="o">&</span> <span class="n">topic</span><span class="o">.</span><span class="n">lesson_order</span> <span class="o">==</span> <span class="n">topic</span><span class="o">.</span><span class="n">lesson_order</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>This failed because the order in which the comparison happens matters.</p>
<figure class='code'><figcaption><span>order-matters</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">lesson_order</span> <span class="o">=</span> <span class="o">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="o">]</span>
</span><span class='line'><span class="n">completed_lessons</span> <span class="o">=</span> <span class="o">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="o">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">lesson_order</span> <span class="o">&</span> <span class="n">completed_lessons</span>
</span><span class='line'> <span class="c1"># => [3, 2, 5]</span>
</span><span class='line'>
</span><span class='line'><span class="n">completed_lessons</span> <span class="o">&</span> <span class="n">lesson_order</span>
</span><span class='line'> <span class="c1"># => [5, 2, 3]</span>
</span><span class='line'>
</span><span class='line'><span class="n">completed_lessons</span> <span class="o">&</span> <span class="n">lesson_order</span> <span class="o">==</span> <span class="n">lesson_order</span>
</span><span class='line'> <span class="c1"># => false</span>
</span></code></pre></td></tr></table></div></figure>
<h2>Win</h2>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">topic_complete?</span>
</span><span class='line'> <span class="n">topic</span><span class="o">.</span><span class="n">lesson_order</span> <span class="o">&</span> <span class="n">completed_lessons</span> <span class="o">==</span> <span class="n">topic</span><span class="o">.</span><span class="n">lesson_order</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h2>BONUS: The Algorithm Behind the Set Intersection Operator</h2>
<p>I took a a deep dive into Ruby source code to figure this one out. Full disclosure: I’ve never read or written C in my life, but with the help of the <a href="http://rxr.whitequark.org/mri/ident">MRI Identifier Search</a>, I was able to piece together how the algorith works.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'> <span class="k">static</span> <span class="n">VALUE</span>
</span><span class='line'><span class="nf">rb_ary_and</span><span class="p">(</span><span class="n">VALUE</span> <span class="n">ary1</span><span class="p">,</span> <span class="n">VALUE</span> <span class="n">ary2</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">VALUE</span> <span class="n">hash</span><span class="p">,</span> <span class="n">ary3</span><span class="p">,</span> <span class="n">v</span><span class="p">;</span>
</span><span class='line'> <span class="n">st_table</span> <span class="o">*</span><span class="n">table</span><span class="p">;</span>
</span><span class='line'> <span class="n">st_data_t</span> <span class="n">vv</span><span class="p">;</span>
</span><span class='line'> <span class="kt">long</span> <span class="n">i</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="n">ary2</span> <span class="o">=</span> <span class="n">to_ary</span><span class="p">(</span><span class="n">ary2</span><span class="p">);</span>
</span><span class='line'> <span class="n">ary3</span> <span class="o">=</span> <span class="n">rb_ary_new</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">RARRAY_LEN</span><span class="p">(</span><span class="n">ary2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">ary3</span><span class="p">;</span>
</span><span class='line'> <span class="n">hash</span> <span class="o">=</span> <span class="n">ary_make_hash</span><span class="p">(</span><span class="n">ary2</span><span class="p">);</span>
</span><span class='line'> <span class="n">table</span> <span class="o">=</span> <span class="n">rb_hash_tbl_raw</span><span class="p">(</span><span class="n">hash</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="k">for</span> <span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">RARRAY_LEN</span><span class="p">(</span><span class="n">ary1</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">v</span> <span class="o">=</span> <span class="n">RARRAY_AREF</span><span class="p">(</span><span class="n">ary1</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span><span class='line'> <span class="n">vv</span> <span class="o">=</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="n">v</span><span class="p">;</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">st_delete</span><span class="p">(</span><span class="n">table</span><span class="p">,</span> <span class="o">&</span><span class="n">vv</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'> <span class="n">rb_ary_push</span><span class="p">(</span><span class="n">ary3</span><span class="p">,</span> <span class="n">v</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="n">ary_recycle_hash</span><span class="p">(</span><span class="n">hash</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="k">return</span> <span class="n">ary3</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>The key to understanding this is in the <code>for</code> loop.</p>
<ul>
<li>ary1 and ary2 represent the arrays for which we’re finding the intersection. ary3 is what the function <code>rb_ary_and</code> returns.</li>
<li>ary2 is turned into a hash table so that elements from ary1 can be easily matched up.</li>
<li>v represents <code>ary1[i]</code>, in Ruby-speak.</li>
<li>vv is somehow tied to that value.</li>
<li><code>st_delete</code> returns 1 if <code>vv</code> was successfully deleted from <code>table</code>, which really refers to ary2, and 0 if it wasn’t found. If it gets deleted, then that means ary2 must have had an element in common; push that element into ary3.</li>
</ul>
<h2>O(x+y)</h2>
<p>In the worst-case scenario, the algorithm iterates through ary2 to create a table, giving us O(x) for <em>x</em> elements in ary2. Then, given there are <em>y</em> elements in ary1, we iterate through ary1 <em>y</em> times and look for the value in the hash table, giving us O(y). Therefore, in total, the algorithm has a big-o of O(x+y).</p>
</div>
<div class="meta">
<div class="date">
<time datetime="2014-04-24T09:51:00-04:00" pubdate data-updated="true">Apr 24<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/array-operators/'>array-operators</a>, <a class='category' href='/blog/categories/big-o/'>big-o</a>, <a class='category' href='/blog/categories/rails/'>rails</a>, <a class='category' href='/blog/categories/ruby/'>ruby</a>, <a class='category' href='/blog/categories/set-intersection-operator/'>set-intersection-operator</a>
</div>
<div class="comments"><a href="/blog/2014/04/24/ruby-array-set-intersection/#disqus_thread">Comments</a></div>
</div>
</article>
<article class="post">
<h2 class="title">
<a href="/blog/2014/04/08/tdd3-TestingHooks/">
Testing Rails Callbacks: A Step in the Right Direction</a>
</h2>
<div class="entry-content">
<p>Anyone who’s worked with tightly-coupled models in rails will likely know the pain of tracing the stack for an error triggered from a callback method. Such painful experiences have led developers to come to a consensus on general rules like <a href="http://blog.bignerdranch.com/1658-the-only-acceptable-use-for-callbacks-in-rails-ever/">“Use a callback only when the logic refers to state internal to the object”</a>, according to Jonathan Wallace. More on this topic by Samuel Mullen in a great blogpost, <a href="http://www.samuelmullen.com/2013/05/the-problem-with-rails-callbacks/">The Problem with Rails Callbacks</a>.</p>
<p>The following post revolves around an <code>Invitation</code> model I wrote with my team mates and then later debated the callback to use.</p>
<p>The <code>Invitation</code> model generates a unique token which it uses to identify users who have clicked on a registration link.</p>
<p>The callback I chose to use first was <code>after_initialize</code> because an <code>invite</code> object must always have a <code>token</code>.</p>
<figure class='code'><figcaption><span>invitation.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Invitation</span> <span class="o"><</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span>
</span><span class='line'> <span class="n">after</span> <span class="kp">initialize</span> <span class="ss">:add_token</span> <span class="c1">#NOTE my syntax highlighter dislikes the underscore. see below.</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">add_unique_token</span>
</span><span class='line'> <span class="nb">self</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="no">Tokenizer</span><span class="o">.</span><span class="n">Generate</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p><strong>NOTE</strong> <code>after initialize</code> above should be <code>after_initialize</code>. For some reason my syntax highlighting plugin doesn’t like the underscore in the correct version.</p>
<p>The associated test:</p>
<figure class='code'><figcaption><span>invitation_spec.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">describe</span> <span class="no">Invitation</span> <span class="k">do</span>
</span><span class='line'> <span class="n">it</span> <span class="s2">"generates a random token on initialize"</span> <span class="k">do</span>
</span><span class='line'> <span class="n">invite</span> <span class="o">=</span> <span class="no">Invitation</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'> <span class="n">expect</span><span class="p">(</span><span class="n">invite</span><span class="o">.</span><span class="n">token</span><span class="p">)</span><span class="o">.</span><span class="n">not_to</span> <span class="n">be_nil</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>However, another team mate suggested using <code>before_create</code> instead.</p>
<p>His model and test:</p>
<figure class='code'><figcaption><span>invitation.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Invitation</span> <span class="o"><</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span>
</span><span class='line'> <span class="n">before_create</span> <span class="ss">:add_token</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">add_unique_token</span>
</span><span class='line'> <span class="nb">self</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="no">Tokenizer</span><span class="o">.</span><span class="n">generate</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>invitation_spec.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">describe</span> <span class="no">Invitation</span> <span class="k">do</span>
</span><span class='line'> <span class="n">it</span> <span class="s2">"generates a random token before create"</span> <span class="k">do</span>
</span><span class='line'> <span class="n">invite</span> <span class="o">=</span> <span class="no">Invitation</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'> <span class="n">expect</span><span class="p">(</span><span class="n">invite</span><span class="o">.</span><span class="n">token</span><span class="p">)</span><span class="o">.</span><span class="n">to</span> <span class="n">be_nil</span>
</span><span class='line'> <span class="n">invite</span><span class="o">.</span><span class="n">save</span>
</span><span class='line'> <span class="n">expect</span><span class="p">(</span><span class="n">invite</span><span class="o">.</span><span class="n">token</span><span class="p">)</span><span class="o">.</span><span class="n">not_to</span> <span class="n">be_nil</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h3>Why does this subtle change matter?</h3>
<p>First, <strong>using <code>after_initialize</code> could produce a false positive.</strong> While the <code>after_initialize</code> test does exactly what the <code>it</code> statement says, there’s a chance that we may miss, say, a validation error that happens before <code>save</code>. This test would pass, and so would the validations, but for some reason you might find that your invitations aren’t working properly. <code>after_initialize</code> allows us to omit saving from the test, which one could generally assume is always desired given that callbacks should only “refer to state internal to an object”.</p>
<p>Additionally, <strong>if you’re testing a callback that affects the internal state of an object, we must test for a state-change.</strong> Using <code>after_initialize</code>, we can tell that a new invite has a token. However, we cannot say that we’ve tested the non-presence and the presence of the token. The pivotal point again is around <code>#save</code>. <code>#save</code> triggers the change and we can say with certainty that we’ve not only seen a “zero to one” change happen, but that the change has persisted in our database.</p>
<p>UPDATE: <a href="https://twitter.com/scottadhoc/status/453917228648640512">Twitter comment</a> from <a href="https://twitter.com/scottadhoc">@scottadhoc</a>: “what happens if you load that record from the db into a new object and then assert on that field?”</p>
<p>Good point! If I understand your suggestion correctly, here’s how I might refactor the after_initialize version of the spec:</p>
<figure class='code'><figcaption><span>invitation_spec.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">describe</span> <span class="no">Invitation</span> <span class="k">do</span>
</span><span class='line'> <span class="n">it</span> <span class="s2">"generates a random token #after_initialize"</span> <span class="k">do</span>
</span><span class='line'> <span class="n">invite</span> <span class="o">=</span> <span class="no">Invitation</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'> <span class="n">expect</span><span class="p">(</span><span class="n">invite</span><span class="o">.</span><span class="n">token</span><span class="p">)</span><span class="o">.</span><span class="n">not_to</span> <span class="n">be_nil</span>
</span><span class='line'> <span class="n">invite</span><span class="o">.</span><span class="n">save!</span>
</span><span class='line'> <span class="n">expect</span><span class="p">(</span><span class="n">invite</span><span class="o">.</span><span class="n">token</span><span class="p">)</span><span class="o">.</span><span class="n">not_to</span> <span class="n">be_nil</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>This way, we can make sure that the data persisted. While this works, my feeling is that the implication of testing after_initialize allows one to omit the persistence part. I certainly fell into that trap and wouldn’t be surprised if I forget again while testing an after_initialize callback.</p>
<p>Lastly, if you use <code>after_initialize</code> with the underscore in a block of code in <code>Octopress</code>, your blog will refuse to generate. Coincidence? I think not.</p>
</div>
<div class="meta">
<div class="date">
<time datetime="2014-04-08T09:00:00-04:00" pubdate data-updated="true">Apr 8<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/callbacks/'>callbacks</a>, <a class='category' href='/blog/categories/rails/'>rails</a>, <a class='category' href='/blog/categories/rspec/'>rspec</a>, <a class='category' href='/blog/categories/ruby/'>ruby</a>, <a class='category' href='/blog/categories/tdd/'>tdd</a>
</div>
<div class="comments"><a href="/blog/2014/04/08/tdd3-TestingHooks/#disqus_thread">Comments</a></div>
</div>
</article>
<article class="post">
<h2 class="title">
<a href="/blog/2014/01/15/tdd2-RSpecMatchers/">
RSpec Custom Matchers: A Deep Dive</a>
</h2>
<div class="entry-content">
<h1>What’s a Matcher?</h1>
<p><code>expect(dan.current_zipcode).to eq(10002)</code></p>
<p>In the line above, the <code>matcher</code> is the method <code>eq</code> because RSpec will check to see if the value of <code>dan.current_zipcode</code> matches <code>10002</code>.</p>
<p>Let’s say that this was a line you wrote for as part of a test for a location tracking app. You want your code to be as clear as possible for collaborators or even for your future self.</p>
<p>Wouldn’t it sound even better if you could write this?</p>
<p><code>expect(dan).to be_in_zipcode(10002)</code></p>
<p>This requires <code>be_in_zipcode</code> to be a method in <code>RSpec</code>’s matcher library. I’m going to briefly explain how to create this new matcher, but for alternate explanations, check out the <a href="https://github.com/dchelimsky/rspec/wiki/Custom-Matchers">Rspec Github Wiki</a> and Chapter 7 of Aaron Sumner’s <a href="https://leanpub.com/everydayrailsrspec">Everyday Rails Testing with RSpec</a>.</p>
<p>My intention is not to write another Matcher tutorial (though this might inevitably happen). After reading Sumner’s chapter, I could imagine how matchers were created but ultimately, I felt a bit uncertain. With a little bit of <code>Pry</code> magic and doc-digging, I think I’ve finally put most of the puzzle together which I’m looking forward to sharing below! Constructive feedback and deeper insights are always welcome. :)</p>
<h1>Match-Maker, Match-Maker, Make Me a Match!</h1>
<p>Let’s write some code so that we can use the method <code>be_in_zipcode(10002)</code> from above.</p>
<p>General syntax at bare minimum first:</p>
<figure class='code'><figcaption><span>syntax.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="ss">RSpec</span><span class="p">:</span><span class="ss">:Matchers</span><span class="o">.</span><span class="n">define</span> <span class="ss">:new_matcher_name</span> <span class="k">do</span> <span class="o">|</span><span class="n">expected</span><span class="o">|</span>
</span><span class='line'> <span class="n">match</span> <span class="k">do</span> <span class="o">|</span><span class="n">actual</span><span class="o">|</span>
</span><span class='line'> <span class="c1"># Lines of code you want this matcher to run</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#optional description and failure message definition blocks</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># From the describe block:</span>
</span><span class='line'><span class="c1"># expect(actual).to matcher_method(expected)</span>
</span></code></pre></td></tr></table></div></figure>
<p>NOTE: Store your matcher files in <code>spec/support/matchers/</code> and require them in <code>spec/spec_helper.rb</code> with the following line:</p>
<p><code>Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}</code></p>
<p>Now onto our example:</p>
<figure class='code'><figcaption><span>be_in_zipcode.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="ss">RSpec</span><span class="p">:</span><span class="ss">:Matchers</span><span class="o">.</span><span class="n">define</span> <span class="ss">:be_in_zipcode</span> <span class="k">do</span> <span class="o">|</span><span class="n">zipcode</span><span class="o">|</span>
</span><span class='line'> <span class="n">match</span> <span class="k">do</span> <span class="o">|</span><span class="n">friend</span><span class="o">|</span>
</span><span class='line'> <span class="n">friend</span><span class="o">.</span><span class="n">in_zipcode?</span><span class="p">(</span><span class="n">zipcode</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="c1"># Optional failure messages</span>
</span><span class='line'> <span class="n">failure_message_for_should</span> <span class="k">do</span> <span class="o">|</span><span class="n">actual</span><span class="o">|</span>
</span><span class='line'> <span class="s2">"expected friend to be in zipcode"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">failure_message_for_should_not</span> <span class="k">do</span> <span class="o">|</span><span class="n">actual</span><span class="o">|</span>
</span><span class='line'> <span class="s2">"expected friend not to be in zipcode"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="c1"># Optional method description</span>
</span><span class='line'> <span class="n">description</span> <span class="k">do</span>
</span><span class='line'> <span class="s2">"checks user's current zipcode"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>Again, the failure messages and description are optional blocks. The match block is obviously mandatory. So now that we have our new matcher, let’s check out what’s going on behind the scenes.</p>
<h1>Under the hood</h1>
<p><code>RSpec::Matchers.define :be_in_zipcode do |zipcode|</code></p>
<p>The <code>define</code> method, extended from the DSL module, does the following:</p>
<figure class='code'><figcaption><span>define.rb RSpec::Matchers::DSL#define</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">define</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">&</span><span class="n">declarations</span><span class="p">)</span>
</span><span class='line'> <span class="n">matcher_template</span> <span class="o">=</span> <span class="ss">RSpec</span><span class="p">:</span><span class="ss">:Matchers</span><span class="o">::</span><span class="ss">DSL</span><span class="p">:</span><span class="ss">:Matcher</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">&</span><span class="n">declarations</span><span class="p">)</span>
</span><span class='line'> <span class="n">define_method</span> <span class="nb">name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">expected</span><span class="o">|</span> <span class="c1"># => expected for us is the var zipcode</span>
</span><span class='line'> <span class="n">matcher</span> <span class="o">=</span> <span class="n">matcher_template</span><span class="o">.</span><span class="n">for_expected</span><span class="p">(</span><span class="o">*</span><span class="n">expected</span><span class="p">)</span>
</span><span class='line'> <span class="n">matcher</span><span class="o">.</span><span class="n">matcher_execution_context</span> <span class="o">=</span> <span class="vi">@matcher_execution_context</span> <span class="o">||=</span> <span class="nb">self</span>
</span><span class='line'> <span class="n">matcher</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># name = be_in_zipcode</span>
</span></code></pre></td></tr></table></div></figure>
<p>The second line setting <code>matcher_template</code> initializes an <code>RSpec::Matchers::DSL::Matcher</code> object which stores the method name and the declarations block.</p>
<p><code>define_method</code> then creates the <code>be_in_zipcode</code> method. The next line’s <code>for_expected(*expected)</code> method sets the zipcode as the expected value and your failure messages/description from the matcher template in the second line. The messages and description are stored in the @messages attribute hash.</p>
<p>The next line I’m not sure about since <code>matcher_execution_context</code> refers to an attribute accessor. I don’t see it in the Matcher module either. Any insight here would be great!</p>
<p>Moving onto the last piece: the match block.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'> <span class="n">match</span> <span class="k">do</span> <span class="o">|</span><span class="n">friend</span><span class="o">|</span>
</span><span class='line'> <span class="n">friend</span><span class="o">.</span><span class="n">in_zipcode?</span><span class="p">(</span><span class="n">zipcode</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>RSpec::Match#match</code> stores the given block in <code>@match_block</code>, so essentially, <code>@match_block = friend.in_zipcode?(zipcode)</code>.</p>
<p>Later, when you run your specs with the new matcher, the <code>match_block</code> will get called from the method <code>RSpec::Match#matches?</code>.</p>
<figure class='code'><figcaption><span>matches?</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">matches?</span><span class="p">(</span><span class="n">actual</span><span class="p">)</span>
</span><span class='line'> <span class="vi">@actual</span> <span class="o">=</span> <span class="n">actual</span>
</span><span class='line'> <span class="k">if</span> <span class="vi">@expected_exception</span>
</span><span class='line'> <span class="k">begin</span>
</span><span class='line'> <span class="n">instance_exec</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="o">&</span><span class="vi">@match_block</span><span class="p">)</span>
</span><span class='line'> <span class="kp">true</span>
</span><span class='line'> <span class="k">rescue</span> <span class="vi">@expected_exception</span>
</span><span class='line'> <span class="kp">false</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'> <span class="k">else</span>
</span><span class='line'> <span class="k">begin</span>
</span><span class='line'> <span class="n">instance_exec</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="o">&</span><span class="vi">@match_block</span><span class="p">)</span>
</span><span class='line'> <span class="k">rescue</span> <span class="ss">Spec</span><span class="p">:</span><span class="ss">:Expectations</span><span class="o">::</span><span class="no">ExpectationNotMetError</span>
</span><span class='line'> <span class="kp">false</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>And that’s it!</p>
<p>So if I were to run the original line, <code>expect(dan).to be_in_zipcode(10002)</code>, the following would happen:</p>
<ol>
<li><code>expect(dan)</code> returns an <code>RSpec::Expectations::ExpectationTarget</code> object storing the object <code>dan</code>. Specifically: <code>=> #<RSpec::Expectations::ExpectationTarget:0x007fbf511e4c78 @target=#<User id: 1, name: dan>></code></li>
<li>the <code>to</code> method passes in <code>be_in_zipcode(10002)</code> and calls a method called <code>handle_matcher</code>…</li>
<li>… which checks if <code>be_in_zipcode</code> has been defined as a matcher.</li>
<li>Since we’ve defined <code>be_in_zipcode</code>, <code>matches?</code> gets called our block, which we saw above.</li>
<li><code>handle_matcher</code> then figures out how to respond, given the messages you passed in when you defined the new matcher.</li>
</ol>
<p>That’s our deep dive into RSpec’s Custom Matchers. Again, feedback always welcome. Hope you enjoyed the complexity as much as I did! :)</p>
</div>
<div class="meta">
<div class="date">
<time datetime="2014-01-15T06:40:00-05:00" pubdate data-updated="true">Jan 15<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/matcher/'>matcher</a>, <a class='category' href='/blog/categories/matchers/'>matchers</a>, <a class='category' href='/blog/categories/rails/'>rails</a>, <a class='category' href='/blog/categories/rspec/'>rspec</a>, <a class='category' href='/blog/categories/ruby/'>ruby</a>, <a class='category' href='/blog/categories/tdd/'>tdd</a>
</div>
<div class="comments"><a href="/blog/2014/01/15/tdd2-RSpecMatchers/#disqus_thread">Comments</a></div>
</div>
</article>
<article class="post">
<h2 class="title">
<a href="/blog/2014/01/13/tdd1-ActiveRecordEqualityRogue/">
ActiveRecord, Equality, and Rogue</a>
</h2>
<div class="entry-content">
<p><img class="right" src="http://static.comicvine.com/uploads/original/8/85629/1887574-rogue1.gif" title="Rogue" >
Almost done with my model specs! I ran into a couple of interesting problems that I posted on Stack Overflow, one of which I’ll cover briefly below. Oh yeah, and Rogue! I’ll explain that in the last section of this post.</p>
<h2>The problem I ran into (from my <a href="https://stackoverflow.com/questions/21102549/why-is-the-where-query-in-rails-returning-a-different-object">StackOverflow post</a>)</h2>
<p><em>If you just read the whole post, skip to the last section of this blog post.</em></p>
<p>I’m testing chats between users in my app. I’m using RSpec and FactoryGirl</p>
<p>The test that’s not passing:</p>
<figure class='code'><figcaption><span>chat_spec.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">it</span> <span class="s2">"creates a chat if one does not exist"</span> <span class="k">do</span>
</span><span class='line'> <span class="n">bob</span> <span class="o">=</span> <span class="n">create</span><span class="p">(</span><span class="ss">:user</span><span class="p">,</span> <span class="ss">username</span><span class="p">:</span> <span class="s2">"bob"</span><span class="p">)</span>
</span><span class='line'> <span class="n">dan</span> <span class="o">=</span> <span class="n">create</span><span class="p">(</span><span class="ss">:user</span><span class="p">,</span> <span class="ss">username</span><span class="p">:</span> <span class="s2">"dan"</span><span class="p">)</span>
</span><span class='line'> <span class="n">new_chat</span> <span class="o">=</span> <span class="no">Chat</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="n">dan</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">chatted_user_id</span><span class="p">:</span> <span class="n">bob</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</span><span class='line'> <span class="n">expect</span><span class="p">(</span><span class="no">Chat</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="s2">"chatted_user_id = ?"</span><span class="p">,</span> <span class="n">bob</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">first</span><span class="p">)</span><span class="o">.</span><span class="n">to</span> <span class="n">equal</span><span class="p">(</span><span class="n">new_chat</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>The failure message says:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>Failure/Error: expect<span class="o">(</span>Chat.where<span class="o">(</span><span class="s2">"chatted_user_id = ?"</span>, bob.id<span class="o">)</span>.first<span class="o">)</span>.to equal<span class="o">(</span>new_chat<span class="o">)</span>
</span><span class='line'>
</span><span class='line'> expected <span class="c">#<Chat:70120833243920> => #<Chat id: 2, user_id: 2, chatted_user_id: 3></span>
</span><span class='line'> got <span class="c">#<Chat:70120833276240> => #<Chat id: 2, user_id: 2, chatted_user_id: 3></span>
</span><span class='line'>
</span><span class='line'> Compared using equal?, which compares object identity,
</span><span class='line'> but expected and actual are not the same object. Use
</span><span class='line'> <span class="sb">`</span>expect<span class="o">(</span>actual<span class="o">)</span>.to eq<span class="o">(</span>expected<span class="o">)</span><span class="sb">`</span> <span class="k">if </span>you don<span class="err">'</span>t care about
</span><span class='line'> object identity in this example.
</span></code></pre></td></tr></table></div></figure>
<p>Why is my query returning a different object id?</p>
<h3>Answer from Simone Carletti on StackOverflow</h3>
<p>equal checks object identity. The objects you are testing are two objects (instances) referencing the same record, but they are actually different objects from a Ruby virtual machine point of view.</p>
<p>You should use</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">expect</span><span class="p">(</span><span class="no">Chat</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="s2">"chatted_user_id = ?"</span><span class="p">,</span> <span class="n">bob</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">first</span><span class="p">)</span><span class="o">.</span><span class="n">to</span> <span class="n">eq</span><span class="p">(</span><span class="n">new_chat</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>To better understand the problem, look at the following example</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="mi">2</span><span class="o">.</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">p353</span> <span class="p">:</span><span class="mo">001</span> <span class="o">></span> <span class="s2">"foo"</span><span class="o">.</span><span class="n">object_id</span>
</span><span class='line'> <span class="o">=></span> <span class="mi">70117320944040</span>
</span><span class='line'><span class="mi">2</span><span class="o">.</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">p353</span> <span class="p">:</span><span class="mo">002</span> <span class="o">></span> <span class="s2">"foo"</span><span class="o">.</span><span class="n">object_id</span>
</span><span class='line'> <span class="o">=></span> <span class="mi">70117320962820</span>
</span></code></pre></td></tr></table></div></figure>
<p>Here I’m creating two identical strings. They are identical, but not equal because they are actually two different objects.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="mi">2</span><span class="o">.</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">p353</span> <span class="p">:</span><span class="mo">00</span><span class="mi">8</span> <span class="o">></span> <span class="s2">"foo"</span> <span class="o">==</span> <span class="s2">"foo"</span>
</span><span class='line'> <span class="o">=></span> <span class="kp">true</span>
</span><span class='line'><span class="mi">2</span><span class="o">.</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">p353</span> <span class="p">:</span><span class="mo">00</span><span class="mi">9</span> <span class="o">></span> <span class="s2">"foo"</span><span class="o">.</span><span class="n">equal?</span> <span class="s2">"foo"</span>
</span><span class='line'> <span class="o">=></span> <span class="kp">false</span>
</span></code></pre></td></tr></table></div></figure>
<p>That’s the same issue affecting your test. equal checks if two objects are actually the same at the object_id level. But what you really want to know is if they are the same record.</p>
<h2>So what’s happening under the hood?</h2>
<p>The “where” query returns an array of objects matching the query, and those objects must be Active Record objects that just handle the data. If I make another query, Active Record must be creating another set of objects to handle each row of data.</p>
<p>I wanted to confirm this before throwing it out on the web as “fact”, so here’s what an Active Record object is from <a href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">Martin Fowler himself</a>:</p>
<blockquote><p>An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.</p></blockquote>
<p>Think of an Active Record object sort of like Rogue (see above). For those of you who don’t remember, Rogue absorbs the memories and abilities of any person she touches.</p>
<p><img src="http://31.media.tumblr.com/25cd14bae1b207202d0ee9b56b475409/tumblr_mzd6fjLYmf1sqhdy2o1_1280.png" width="480" title="Comic Picture Rogue's Powers" ></p>
<p>Similarly (sorta), an Active Record objects takes the data (memories) of a certain row and then takes on the behavior (abilities) of the object type matching the table name.</p>
<p>Ok, so that was really just an excuse to get Rogue somewhere on my blog. While I’m at it, here’s one of her destroying Ororo (Storm).</p>
<p><img src="http://i22.photobucket.com/albums/b310/RogueX18/Rogue%20Absorptions/UncannyX-Men158Storm.jpg" title="Rogue and Storm Picture" ></p>
<p>So there you have it! Moral of the story: generally remember to use eq to test equivalence in RSpec with ActiveRecord.</p>
<p>Oh, and here’s a <a href="https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/equality-matchers">bonus resource: equal, eql, eq, and ==</a> in RSpec.</p>
</div>
<div class="meta">
<div class="date">
<time datetime="2014-01-13T23:00:00-05:00" pubdate data-updated="true">Jan 13<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/activerecord/'>activerecord</a>, <a class='category' href='/blog/categories/rails/'>rails</a>, <a class='category' href='/blog/categories/rspec/'>rspec</a>, <a class='category' href='/blog/categories/ruby/'>ruby</a>, <a class='category' href='/blog/categories/tdd/'>tdd</a>
</div>
<div class="comments"><a href="/blog/2014/01/13/tdd1-ActiveRecordEqualityRogue/#disqus_thread">Comments</a></div>
</div>
</article>
<article class="post">
<h2 class="title">
<a href="/blog/2014/01/12/tdd0-whyttd/">
How and Why I Began Testing in Ruby on Rails</a>
</h2>
<div class="entry-content">
<p>Testing is one of those things that feels a bit like eating well or going to the gym. Since it’s already ten days into the New Year and I have yet to commit to any resolutions, let this be it: no more will I make excuses for skipping testing.</p>
<p>What does this really mean to me though? Am I eating broccoli just because someone told me it’s good for me? Here are three reasons that have driven me to make the change.</p>
<h2>TDD Reason 1: Manual Testing Sucks; TDD Saves Time</h2>
<p>My friend told me about the job she left before coming to the Flatiron School and one of her responsibilities looked a bit like this:</p>
<p><img src="http://blog.polarion.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-06-at-12.07.14-PM.png"></p>
<p>What. A. Nightmare. There should be a -phobia for this.</p>
<p>Don’t get me wrong — I’m sure this could be pretty efficient if the scope of the UX is very small, or you don’t know-how to implement TDD yet. However, how can you be sure your site won’t expand, or why not learn how to use a gem like Capybara to save you time in the future? Used in conjuction with Guard, you could really save some serious time while coding!</p>
<h2>TDD Reason 2: Code Confidence</h2>
<p>Now that I’ve had a bit more experience writing web apps (still without TDD), I’ve had the pleasure of seeing them grow and change throughout development. On the other hand, everytime I implemented a new feature, I had less and less confidence that the rest of my code base would work fine. At some point, the prospect of a new feature started feeling like a laundry list or the guarantee of a new bug. Testing will certainly help me find bugs as I introduce them, and therefore boost my confidence in in my code.</p>
<h2>TDD Reason 3: Thinking Before Doing</h2>
<p>Writing tests before writing production code forces you to clearly iterate what it is you want your application to do before you start coding. Ideally, you want your tests to last as long as possible as well, so it will force you to make important decisions about design as well. The prospect of having well thought-out code with lasting design excites me! I’ve had several experiences already of trying to refactor poorly designed code and it’s quite painful.</p>
<h2>My Next Steps</h2>
<p>I’ve decided to begin my TDD exploration by refactoring my first app, Little Red Wagon (LRW). My current reads are Aaron Sumner’s book, <a href="https://leanpub.com/everydayrailsrspec">Everyday Rails Testing with RSpec</a>, and <a href="http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330">Practical Object-Oriented Design in Ruby</a> by Sandi Metz. I’m about 30% through each book right now and have written a few model specs already for LRW. I’ve decided not to use Factory Girl since it will slow down testing and Rails’ built-in fixtures are satisfactory for what I currently have. In any case, the grand plan is to get some hands-on practice writing tests using the TDD book first and then taking on the much larger challenge of redesigning my code base. Thanks for reading, and more updates to come on TDD!</p>
</div>
<div class="meta">
<div class="date">
<time datetime="2014-01-12T23:00:00-05:00" pubdate data-updated="true">Jan 12<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/rails/'>rails</a>, <a class='category' href='/blog/categories/rspec/'>rspec</a>, <a class='category' href='/blog/categories/ruby/'>ruby</a>, <a class='category' href='/blog/categories/tdd/'>tdd</a>
</div>
<div class="comments"><a href="/blog/2014/01/12/tdd0-whyttd/#disqus_thread">Comments</a></div>
</div>
</article>
<article class="post">
<h2 class="title">
<a href="/blog/2014/01/05/big-o/">
Big O Notation</a>
</h2>
<div class="entry-content">
<p>Big O notation might look something like this: O(log N)</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>N = number of input data
</span><span class='line'>O( ) = function notation for Big O (just tells you we're using Big O notation)
</span><span class='line'>log N = the function that describes the efficiency of the procedure or algorithm as N grows bigger and bigger</span></code></pre></td></tr></table></div></figure>