-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
717 lines (513 loc) · 59.5 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Incandescent Software]]></title>
<link href="http://incandescent.github.com/atom.xml" rel="self"/>
<link href="http://incandescent.github.com/"/>
<updated>2012-02-04T22:38:01-05:00</updated>
<id>http://incandescent.github.com/</id>
<author>
<name><![CDATA[Incandescent Team]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[IthacaTech Podcast Episode 1 Interview with Casey Dreier]]></title>
<link href="http://incandescent.github.com/blog/2011/07/18/ithacatech-podcast-episode-1-interview-with-casey-dreier/"/>
<updated>2011-07-18T23:57:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/07/18/ithacatech-podcast-episode-1-interview-with-casey-dreier</id>
<content type="html"><![CDATA[<p><strong>IthacaTech Podcast - Episode 1 Interview with Casey Dreier</strong></p>
<p><a href="http://podcast.incandescentsoftware.com/s0/E1-Interview_with_Casey_Dreier.mp3" title="Episode 1 - Interview with Casey Dreier" target="_blank">Direct link</a></p>
<p>Episode 1 is out! In this episode we interview Rails developer Casey Dreier. Casey is a lead Ruby on Rails developer and evangelist at SingleBrook Technology, Inc. in Ithaca, NY.</p>
<p>We discuss Ruby, Rails, Casey’s recent Rails bug fixes, the James Webb Space Telescope, and our thoughts on fostering the Ithaca developer community.</p>
<p>We’ve upgraded to some new-fangled audio equipment, so look forward to improved audio quality (and maybe production skills to match in the future).</p>
<p>Please send feedback, suggestions, and angry screeds to <a href="mailto:[email protected]" target="_blank">[email protected]</a>.</p>
<p>- Aaron</p>
<p>Links:</p>
<ul>
<li><a href="http://rubyrogues.com/" title="Ruby Rogues podcast" target="_blank">Ruby Rogues podcast</a></li>
<li><a href="http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/" title="Ruby blocks, procs and lambdas" target="_blank">Ruby blocks, procs, and lambdas</a></li>
<li><a href="http://blogs.discovermagazine.com/badastronomy/2011/07/07/congress-puts-nasa-and-jwst-on-the-chopping-block/" title="James Webb Space Telescope funding in the air" target="_blank">James Webb Space Telescope funding in the air</a></li>
<li><a href="http://groups.google.com/group/ithaca-web-people" target="_blank">“Ithaca Web People”</a> Google group. If you are in Ithaca and you do (web) development, and you are a person, sign up and check out our meetups and hackfests!</li>
</ul>
<p>Our new audio setup, thanks to <a href="http://castroller.com/Podcasts/LinuxOutlaws/2247549-Linux%20Outlaws%20200%20-%20Winning!%20Podcast%20Production%20Special" target="_blank">Linux Outlaws for details on their production process</a> </p>
<ul>
<li><a href="http://www.behringer.com/EN/Products/B-1.aspx" target="_blank">Behringer B1</a> condenser mic</li>
<li><a href="http://www.behringer.com/EN/Products/MIC100.aspx" target="_blank">Behringer MIC100</a> mic pre-amp</li>
<li><a href="http://www.behringer.com/EN/Products/UCA202.aspx" target="_blank">Behringer UCA202</a> audio interface</li>
<li>MacBook built in microphone uber alles</li>
</ul>
<p>And thanks to people giving us weird looks as we blithely tested our equipment. <3</p>
<p>Podcast info</p>
<ul>
<li>Theme song by <a href="http://www.bradsucks.net/" target="_blank">Brad Sucks</a>, <em>Flouride (demo)</em>.</li>
<li>RSS feed: <a href="http://feeds.feedburner.com/incandescentsoftware/IthacaTechPodcast">http://feeds.feedburner.com/incandescentsoftware/IthacaTechPodcast</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Extending Jasmine Matchers]]></title>
<link href="http://incandescent.github.com/blog/2011/07/03/extending-jasmine-matchers/"/>
<updated>2011-07-03T01:55:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/07/03/extending-jasmine-matchers</id>
<content type="html"><![CDATA[<p><a href="http://pivotal.github.com/jasmine/">Jasmine</a> is a behavior-driven development framework for testing JavaScript from <a href="http://pivotallabs.com/">Pivotal Labs </a> (I believe <a href="http://agaskar.com/">Rajan Agaskar</a> was/is the original author). I’ve been using Jasmine for a while now to test my JavaScript code. Today I ran into interesting situation where I wanted to test events bound to jQuery element. Basically by writing code like this:</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='javascript'><span class='line'><span class="nx">$</span><span class="p">(</span><span class="s1">'#el'</span><span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="s1">'click'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">// handler code goes here</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>I wanted to know if element <strong>$(‘#el’)</strong> had any events attached to it. I looked around but couldn’t find any predefined matchers in jasmine or <a href="https://github.com/velesin/jasmine-jquery">jasmine-jquery</a> to accomplish it. I realized that it’s pretty easy to extend jasmine and define my own matchers (which is pretty cool). Here is how you can do it:</p>
<p>First create your new matchers:</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>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">eventMatchers</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">toHaveEvent</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">jQuery</span><span class="p">.</span><span class="nx">data</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">actual</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
</span><span class='line'> <span class="k">for</span> <span class="p">(</span><span class="nx">obj</span> <span class="k">in</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">obj</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'> <span class="k">for</span> <span class="p">(</span><span class="nx">eventName</span> <span class="k">in</span> <span class="nx">data</span><span class="p">[</span><span class="nx">obj</span><span class="p">].</span><span class="nx">events</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">[</span><span class="nx">obj</span><span class="p">].</span><span class="nx">events</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">eventName</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">event</span> <span class="o">===</span> <span class="nx">eventName</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="kc">true</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="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure>
<p>Then in your spec add your matchers inside beforeEach:</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>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">describe</span><span class="p">(</span><span class="s2">"Element"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">beforeEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">addMatchers</span><span class="p">(</span><span class="nx">eventMatchers</span><span class="p">);</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>That’s it! Now you can use your new matchers inside your spec. In this case I was able to use it like this:</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>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">describe</span><span class="p">(</span><span class="s2">"Element"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">beforeEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">addMatchers</span><span class="p">(</span><span class="nx">eventMatchers</span><span class="p">);</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'>
</span><span class='line'> <span class="nx">describe</span><span class="p">(</span><span class="s2">"when event attached"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">it</span><span class="p">(</span><span class="s2">"should contain attached event"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">setFixtures</span><span class="p">(</span><span class="s2">"&lt;div id='el'&gt;&lt;/div&gt;"</span><span class="p">);</span>
</span><span class='line'> <span class="nx">$</span><span class="p">(</span><span class="s1">'#el'</span><span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="s1">'click'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{});</span>
</span><span class='line'> <span class="nx">expect</span><span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">'#el'</span><span class="p">)).</span><span class="nx">toHaveEvent</span><span class="p">(</span><span class="s1">'click'</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="p">});</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Introducing the IthacaTech Podcast]]></title>
<link href="http://incandescent.github.com/blog/2011/06/21/introducing-the-ithacatech-podcast/"/>
<updated>2011-06-21T15:28:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/06/21/introducing-the-ithacatech-podcast</id>
<content type="html"><![CDATA[<p><strong>Introducing the IthacaTech Podcast!</strong></p>
<p><a href="http://podcast.incandescentsoftware.com/s0/E0-The_Rough_In.mp3" title="Episode 0 - The Rough In" target="_blank">Direct link</a> (see below for show notes)</p>
<p>This is something we’ve wanted to do for a while - start an <strong><em>Ithaca-based</em> tech podcast</strong>. Michal and I are always coming across exciting new projects and technologies and we’d like to create a venue for sharing those discoveries and discussions with others, and, conversely, learning from others in the area.</p>
<p>We are aiming for a local focus - we want to highlight local business, events, music, etc. To that end we are looking for:</p>
<ul>
<li><strong>web and other software developers in the area that want to talk about what they are working on</strong></li>
<li><strong>local music we can showcase or use as bumpers</strong></li>
<li><strong>topic and segment ideas, send them in!</strong></li>
<li><strong>feedback and corrections</strong></li>
</ul>
<p>If you have suggestions for podcast topics or would like to get involved with the podcast, let us know at <a href="mailto:[email protected]" target="_blank">[email protected]</a> (or just email us directly :).</p>
<p><em>Note: in the spirit of DIY, we are learning as we go. :) This first episode is pretty rough since we wanted to get our first show out there ASAP, so please excuse the audio quality!</em></p>
<p>- Aaron</p>
<p><strong>Episode 0 - “The Rough In” Thurs. 6/16/11 Show notes</strong></p>
<p>Today Michal discusses JavaScript frameworks and Aaron explains the Fork/Join pattern.</p>
<p>JavaScript frameworks discussed:</p>
<ul>
<li><a href="http://microjs.com/">http://microjs.com/</a></li>
<li><a href="http://documentcloud.github.com/backbone/">http://documentcloud.github.com/backbone/</a></li>
<li><a href="http://angularjs.org/">http://angularjs.org/</a></li>
<li><a href="http://knockoutjs.com/">http://knockoutjs.com/</a></li>
<li><a href="http://www.sproutcore.com/">http://www.sproutcore.com/</a></li>
<li><a href="http://awardwinningfjords.com/2011/05/09/javascript-microframeworks-and-the-future.html">http://awardwinningfjords.com/2011/05/09/javascript-microframeworks-and-the-future.html</a></li>
</ul>
<p>Fork/Join links</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Fork-join_queue">http://en.wikipedia.org/wiki/Fork-join_queue</a></li>
<li><a href="http://gee.cs.oswego.edu/dl/papers/fj.pdf">http://gee.cs.oswego.edu/dl/papers/fj.pdf</a></li>
<li><a href="http://download.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html">http://download.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html</a></li>
<li><a href="http://www.coopsoft.com/ar/CalamityArticle.html">http://www.coopsoft.com/ar/CalamityArticle.html</a></li>
</ul>
<p>Local links</p>
<ul>
<li><a href="http://www.topographymarketing.com/">http://www.topographymarketing.com/</a> (thanks for letting us use your space guys!)</li>
</ul>
<p>Podcast info</p>
<ul>
<li>Theme song by <a href="http://www.bradsucks.net/" target="_blank">Brad Sucks</a>, <em>Flouride (demo)</em>.</li>
<li>RSS feed: <a href="http://feeds.feedburner.com/incandescentsoftware/IthacaTechPodcast">http://feeds.feedburner.com/incandescentsoftware/IthacaTechPodcast</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[A comprehensive list of JavaScript resources]]></title>
<link href="http://incandescent.github.com/blog/2011/06/20/a-comprehensive-list-of-javascript-resources/"/>
<updated>2011-06-20T13:43:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/06/20/a-comprehensive-list-of-javascript-resources</id>
<content type="html"><![CDATA[<p>A few people have asked me lately about books and other resources related to JavaScript. I’ve decided to list them here for reference. </p>
<h3><strong>JavaScript Books:</strong></h3>
<p>There are many books about JavaScript. Some of them are better than others. Here is a list of books I read and recommend:</p>
<ol>
<li><a href="http://www.amazon.com/exec/obidos/ASIN/0596517742/wrrrldwideweb/">JavaScript: The Good Parts</a> by <strong>Douglas Crockford </strong> </li>
<li><a href="http://www.amazon.com/Eloquent-JavaScript-Modern-Introduction-Programming/dp/1593272820 ">Eloquent JavaScript: A Modern Introduction to Programming</a> by <strong>Marijn Haverbeke </strong></li>
<li><a href="http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752/">JavaScript patterns</a> by <strong>Stoyan Stefanov<br /></strong></li>
<li><a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/">Essential JS Design Patterns</a> by <strong>Addy Osmani <br /> </strong></li>
</ol>
<h3><strong>Blogs about JavaScript:</strong></h3>
<ol>
<li><a href="http://javascript.crockford.com">http://javascript.crockford.com</a> by <strong>Douglas Crockford</strong> (a lot of interesting topics)</li>
<li><a href="http://dmitrysoshnikov.com/">http://dmitrysoshnikov.com/</a> by <strong>Dmitry Soshnikov</strong> (fantastic overview of ECMA-262 implementation and more)</li>
<li><a href="http://perfectionkills.com/">http://perfectionkills.com/</a> <strong>by kangax</strong> (exploring javascript by example)</li>
<li><a href="http://javascriptweblog.wordpress.com/">http://javascriptweblog.wordpress.com/</a> by <strong>Angus Croll </strong>(a lot of JS topics usually with great examples)</li>
<li><a href="http://www.adequatelygood.com/">http://www.adequatelygood.com/</a> by <strong>Ben Cherry</strong></li>
<li><a href="http://ejohn.org/category/blog/">http://ejohn.org/category/blog/</a> by <strong>John Resig</strong></li>
<li><a href="http://mir.aculo.us/">http://mir.aculo.us/</a> by <strong>Thomas Fuchs<br /><br /><br /></strong></li>
</ol>
<h3><strong>Websites about JavaScript:</strong></h3>
<ol>
<li><strong>JavaScript Garden</strong>: <a href="http://bonsaiden.github.com/JavaScript-Garden">http://bonsaiden.github.com/JavaScript-Garden</a> (this is a good resource but please also see the feedback about it <a href="https://github.com/BonsaiDen/JavaScript-Garden/issues/84">here</a>)</li>
<li><strong>DailyJS</strong> <a href="http://dailyjs.com/">http://dailyjs.com</a> (every day you can see what’s new in JavaScript world)</li>
<li><strong>JavaScript Weekly</strong> <a href="http://javascriptweekly.com/">http://javascriptweekly.com</a></li>
<li><strong>Annotated ECMAScript 5.1</strong> <a href="http://es5.github.com/">http://es5.github.com</a></li>
<li><strong>Badass JavaScript</strong> <a href="http://badassjs.com">http://badassjs.com</a></li>
</ol>
<p><strong> </strong></p>
<h3><strong>Mailing Lists:</strong></h3>
<ol>
<li><strong><span><strong>JSMentors</strong>: <a href="http://jsmentors.com/">http://jsmentors.com</a> </span></strong>(discussion of JavaScript, mentoring, code reviews)</li>
</ol>
<h3><strong><br /><br />Client-Side JavaScript Frameworks and Tools:</strong></h3>
<p>Frameworks come into many flavors (monolithic, hybrid, micro) and different people advocate for different approaches. You can read more on the topic here: <a href="http://mir.aculo.us/2011/04/11/i-for-one-welcome-our-new-micro-framework-overlords/">http://mir.aculo.us/2011/04/11/i-for-one-welcome-our-new-micro-framework-overlords/</a> and here: <a href="http://tomdale.net/2011/04/imagine-a-beowulf-cluster-of-javascript-frameworks/">http://tomdale.net/2011/04/imagine-a-beowulf-cluster-of-javascript-frameworks/</a> and choose your side or just use the best tool for the job :).</p>
<ol>
<li><strong>Backone.js</strong> <a href="http://documentcloud.github.com/backbone/">http://documentcloud.github.com/backbone/</a> (model centric, evented based)</li>
<li><strong>Spine</strong> <a href="http://maccman.github.com/spine">http://maccman.github.com/spine</a></li>
<li><strong>MicroJS</strong> <a href="http://microjs.com">http://microjs.com</a> (collection of small tools and libraries)</li>
<li><strong>Sproutcore</strong> <a href="http://www.sproutcore.com">http://www.sproutcore.com</a> (version 2.0 is more a hybrid approach)</li>
<li><strong>EmberJS</strong> <a href="http://emberjs.com/">http://emberjs.com</a></li>
<li><strong>ZeptoJS</strong> <a href="http://zeptojs.com">http://zeptojs.com</a> (micro framework which follows jQuery API and targets mobile webkit)</li>
<li><strong>KnockoutJS</strong> <a href="http://knockoutjs.com">http://knockoutjs.com</a> (Model - View - View Model approach)</li>
<li><strong>Angular</strong> <a href="http://angularjs.org">http://angularjs.org</a> (another hybrid with some interesting patterns behind it)</li>
</ol>
<h3><strong>Online JavaScript Tools:</strong></h3>
<ol>
<li><strong>JSFiddle</strong> <a href="http://jsfiddle.net">http://jsfiddle.net</a> (a playground for web developers)</li>
<li><strong>JSLint</strong> <a href="http://www.jslint.com">http://www.jslint.com</a> (The JavaScript Code Quality Tool)</li>
<li><strong>JSHint</strong> <a href="http://jshint.org">http://jshint.org</a> </li>
<li><strong>JSONLint</strong> <a href="http://jsonlint.com">http://jsonlint.com</a> (JSON validator)</li>
<li><strong>jsPerf</strong> <a href="http://jsperf.com">http://jsperf.com</a> (JavaScript performance playground)</li>
</ol>
<p>So there you have it. I’ve been collecting these materials for a while now. This list is not set in stone and I’m curious if you found some other resources worth mentioning. I’m collecting a similar list related to Node.js and CoffeeScript which I may share in the future.</p>
<p>- michal</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Fork/Join]]></title>
<link href="http://incandescent.github.com/blog/2011/06/12/fork-slash-join/"/>
<updated>2011-06-12T19:56:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/06/12/fork-slash-join</id>
<content type="html"><![CDATA[<p>As our computing environment and needs change, certain programming styles and patterns which are less effective recede and others which are more applicable rise in popularity. As these previously implicit patterns are identified and discussed they are ascribed proper names.</p>
<p>“Fork/Join” is one of these patterns which is gaining prominence. It refers to both a simple and ubiquitous concept (intuitive enough that you probably hadn’t thought to name it) and a very specific and narrow implementation of that concept.</p>
<p>Small-f “fork/join” is a general approach to parallelizing a decomposable task. The main task is decomposed into many sub-tasks that can be run independently, these tasks are then run in parallel on multiple threads (forks), and the main task waits (joins) for their completion before proceeding. This can be easily implemented with existing concurrency frameworks such as Java’s Executors facility:</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>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="n">List</span><span class="o"><</span><span class="n">Callable</span><span class="o"><</span><span class="n">Output</span><span class="o">>></span> <span class="n">callables</span> <span class="o">=</span>
</span><span class='line'> <span class="k">new</span> <span class="n">ArrayList</span><span class="o"><</span><span class="n">Callable</span><span class="o"><</span><span class="n">Output</span><span class="o">>>(</span><span class="n">inputs</span><span class="o">.</span><span class="na">size</span><span class="o">());</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="o">(</span><span class="n">Input</span> <span class="nl">i:</span> <span class="n">inputs</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">callables</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="n">Callable</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'> <span class="kd">public</span> <span class="n">Output</span> <span class="nf">call</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'> <span class="c1">// do some work here</span>
</span><span class='line'> <span class="k">return</span> <span class="n">output</span><span class="o">;</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">});</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// following call performs the fork and join</span>
</span><span class='line'><span class="n">List</span><span class="o"><</span><span class="n">Future</span><span class="o"><</span><span class="n">Output</span><span class="o">>></span> <span class="n">futures</span>
</span><span class='line'> <span class="o">=</span> <span class="n">EXECUTOR_SERVICE</span><span class="o">.</span><span class="na">invokeAll</span><span class="o">(</span><span class="n">callables</span><span class="o">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>On the other hand, Fork/Join also refers to a specific application of the “fork/join” pattern which has been proposed by Doug Lea for inclusion in Java 7: <a href="http://gee.cs.oswego.edu/dl/papers/fj.pdf">http://gee.cs.oswego.edu/dl/papers/fj.pdf</a></p>
<p>Going back to our previous fork/join example, note that in a generic implementation tasks will be run on independent threads which will typically block on a single task queue. When the number of threads scales up, and the size of tasks scales down, lock contention on this queue becomes problematic.</p>
<p>The Fork/Join implementation that Doug Lea proposes is aimed at a very specific (I would say narrow), but possibly very common case: parallel algorithms which do not block. When a purely cpu-bound algorithm is parallelized, there will be high contention on any shared queue. The Fork/Join implementation deals with this by using an alternate queuing arrangement call “work stealing”. Instead of all threads pulling from a shared (and contended) queue, each thread has its own dedicated (mostly uncontended) task queue (a deque). Only when a given thread runs out of tasks will contention occur - it will attempt to “steal” a task of the end of another thread’s queue.</p>
<p>The hierarchical (and possibly cyclical) decomposition of tasks, and execution of tasks via a “work stealing” arrangement is what is referred to by “Fork/Join” proper.</p>
<p>There is at least one critique of Fork/Join’s inclusion in Java 7 which seems well reasoned to me: <a href="http://www.coopsoft.com/ar/CalamityArticle.html">http://www.coopsoft.com/ar/CalamityArticle.html</a>. I for one remain skeptical that this implementation will produce significantly better results than the simpler “fork/join” pattern with a standard thread pool and shared queue, to outweigh the cost in implementation and conceptual complexity. However Doug contributed the Executors framework to start with, so he certainly knows his concurrency.</p>
<p>If you’re like me then hopefully the above explanation has cleared up the term “Fork/Join” and distinguished the-pattern-i-was-using-all-along from the very specific framework/library proposal for Java 7.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Spring Application Customization Patterns]]></title>
<link href="http://incandescent.github.com/blog/2011/06/08/spring-application-customization-patterns/"/>
<updated>2011-06-08T23:03:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/06/08/spring-application-customization-patterns</id>
<content type="html"><![CDATA[<p>Having performed numerous customizations of third party or upstream/vendor applications based on the Spring framework, I’d like to share some patterns I’ve identified. These patterns form a hierarchy based on preferability - if it is not possible to implement one approach you may have to back off, and try the next best, repeating in stepwise fashion. I am going to list them from least preferable to most preferable in order to walk you through the rationale behind each approach.</p>
<p>We will assume an application distributed in binary form, containing a Spring context with a service interface <strong>com.sample.ApplicationService</strong> and implementation <strong>com.sample.ApplicationServiceImpl</strong> defined as an <strong>“applicationService”</strong> bean which we want to override with some local customization.</p>
<p><strong>Direct class override</strong></p>
<p>The simplest and most direct approach is to simply create a new class named <strong>com.sample.ApplicationServiceImpl</strong> and arrange for it to appear in the classpath before the upstream implementation. If you have no other options (or are simply prototyping or debugging something) then this might work for you, but it cannot be considered much more than a hack.</p>
<p>There are numerous problems with this approach. First, while it may initially be superficially possible to contrive a classloader chain which results in your implementation being picked up first, this is brittle and may lead to very confusing results when it breaks in the future. You will either be duplicating the service implementation by copying and pasting, or otherwise lying about the pedigree of this class. This will certainly make debugging harder, and will also convey an immediate maintenance overhead. Imagine upstream diverging from the base you forked - you will now have to continually reconcile any future changes to upstream (this may not phase users of decentralized version control systems but is certainly endless and error-prone tedium when working with central SCM like SVN). If you hoped to submit your customizations for inclusion upstream, then overriding the class directly may complicate acceptance. If behavior has changed, tests may fail. Or the change may be rejected because it is not suitable as a default for all users.</p>
<p>A better approach would be to implement a separate class and submit this implementation as an <em>alternative</em> (with tests specific to this implementation of course).</p>
<p><strong>Explicit context inclusion</strong></p>
<p>In order to supply an alternate implementation, you will need to override the service bean defined in the application’s Spring context (let’s assume there <em>is</em> such a bean defined). Unless the application has provided some way for you to inject a context to override this bean you are still in the first situation: having to directly override a file (the Spring context this time) relying on classloader precedence. Let’s assume the application has implemented a specific provision for you to specify your own Spring context for inclusion. It may look like this:</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>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="n">String</span> <span class="n">customContext</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="s">"customContext"</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">(</span><span class="n">customContext</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">context</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ClasspathApplicationContext</span><span class="o">(</span><span class="n">DEFAULT_CTX</span><span class="o">);</span>
</span><span class='line'><span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
</span><span class='line'> <span class="n">context</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ClasspathApplicationContext</span><span class="o">(</span><span class="k">new</span> <span class="n">String</span><span class="o">[]</span> <span class="o">{</span> <span class="n">DEFAULT_CONTEXT</span><span class="o">,</span> <span class="n">customContext</span> <span class="o">});</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>In this situation you can construct a Spring context which redefines the application bean by name (“applicationService”) and supply the context via a system parameter:
<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='java'><span class='line'><span class="o">-</span><span class="n">DcustomContext</span><span class="o">=</span><span class="n">MySpecialCustomization</span><span class="o">.</span><span class="na">xml</span>
</span></code></pre></td></tr></table></div></figure>
<p>However this requires explicit, programmatic, support by the application.</p>
<p><strong>Automatic context inclusion</strong></p>
<p>A better approach for the application to implement is to take advantage of Spring’s resource syntax to import a <strong>wildcard</strong> resource expression. For 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>
</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt"><import</span> <span class="na">resource=</span><span class="s">"classpath*:com/sample/*Customization.xml"</span><span class="nt">></span>
</span></code></pre></td></tr></table></div></figure>
<p>If placed in the application’s context, this expression will cause the import of any contexts matching the glob <strong>“com/sample/*Customization.xml”</strong> in any classloader without any <em>additional coordination between application and implementer.</em></p>
<p>The <strong>“classpath*:” </strong>syntax tells Spring to look in <em>all classloaders</em>. See Spring’s documentation for a better understanding of classpath resource expressions:</p>
<a href="http://static.springsource.org/spring/docs/2.5.x/reference/resources.html#resources-app-ctx-wildcards-in-resource-paths">http://static.springsource.org/spring/docs/2.5.x/reference/resources.html#resources-app-ctx-wildcards-in-resource-paths</a>
<p>If using Maven, for example, simply adding an additional dependency containing the customization (e.g. “com/sample/MySpecialCustomization.xml”) to your project is sufficient to implement the override.</p>
<p>One theoretical downside is that it may be expensive for Spring to iterate through classloaders looking for matching contexts. This is complete speculation on my part, and given the maintenance burden and complexity of the other solutions, it is probably worth a (startup) performance penalty.</p>
<p><strong>Missing bean definition</strong></p>
<p>The above approaches will not work (directly) if you encounter the following situation: You wish to override a class which is not defined as a bean. It is likely this class itself is used (eventually) by a service, which means you need to walk the caller hierarchy to find affected services, and then resume with the above approaches <em>on those services</em>. You will need to override the services, providing implementations (ideally shallow subclasses) which override <em>the minimal number of methods</em>necessary to replace invocations of the old class with your new class.</p>
<p>For bonus points, make the aforementioned class <em>injectable</em>as a Spring bean, and submit this enhancement upstream. This will allow you to migrate your customization to a simple bean and throw away your unnecessary wrapper classes/beans.</p>
<p><strong>AOP magic</strong></p>
<p>With the approaches discussed so far, you ultimately still have to replace an entire service. If the application has been modularized sufficiently then this may not be a concern. However, it may be the case that replacing an entire service is heavy-handed, or that the functionality you need implemented is not necessarily best done by replacing a service implementation.</p>
<p>In these situations there is another trick up our sleeve. We can wrap the <strong><em>existing</em></strong> implementation bean with a Spring AOP (Aspect Oriented Programming) aspect. For example we can surgically override a single method on a large interface. Or we can apply common logic to all methods (e.g. caching). We can secretly mutate method arguments and return values. In some situations this is much more convenient than overriding a service (imaging having to override a large service simply to change arguments and delegate to the wrapper service…).</p>
<p>While this is the most loosely coupled approach, there are several downsides. First, AOP can be hard to understand and maintain. Secondly, AOP can complicate debugging as errors can now occur “between” known call frames, and behavior introduced dynamically via AOP will not be obvious to the external observer. Lastly, AOP can only be applied to services defined as beans.</p>
<p>For details on Spring AOP see:</p>
<a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop.html">http://static.springsource.org/spring/docs/2.5.x/reference/aop.html</a>
<p><strong>Conclusion</strong></p>
<p>Well, despite the lack of code examples I hope that this post has been helpful. I may in the future construct a sample case that illustrates each of these approaches, and the amount of “maintenance” overhead they impose.</p>
<p>To sum up, I’d like to conclude with:</p>
<p>Direct class overriding: JUST DON’T DO IT</p>
<p>Automatic context inclusion: PLEASE implement this provision if you are writing an application or service in Spring which you anticipate users having to customize</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Some News]]></title>
<link href="http://incandescent.github.com/blog/2011/04/26/some-news/"/>
<updated>2011-04-26T23:52:00-04:00</updated>
<id>http://incandescent.github.com/blog/2011/04/26/some-news</id>
<content type="html"><![CDATA[<p>We have some exciting news! First, <a href="http://www.couchbase.com">Couchbase</a> the company behind <a href="http://couchdb.apache.org/">couchdb</a> published a <a href="http://www.couchbase.com/case-studies/incandescent">case study</a> about the <a href="http://menagerievet.com/">Menagerie Whiteboard</a> (Thank you Couchbase :)). Our solution is built entirely in JavaScript and HTML5 (the Couchbase guys are calling this approach <a href="http://couchapp.org/page/index">‘couchapps’</a>) and it’s served directly from couchdb. It means there is no need for the traditional backend. Our JavaScript code is based on the wonderful <a href="http://documentcloud.github.com/backbone/">Backbone.js</a> library.</p>
<p>The second piece of exciting news is that we just released a new version of the whiteboard which now works on iPad (check our demo <a href="http://whiteboard.couchone.com/whiteboard/_design/whiteboard/index.html">here</a>). We redesigned the UI and changed few things around to support the iPad platform.</p>
<p><img src="http://media.tumblr.com/tumblr_lkosj4D0nL1qz7rfi.png" /></p>
<p>We plan to write more about our experience and technical challenges we encountered on the way so please stay tuned.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[jQuery Mobile with Backbone.js and PhoneGap]]></title>
<link href="http://incandescent.github.com/blog/2011/02/10/jquery-mobile-with-backbone-dot-js-and-phonegap/"/>
<updated>2011-02-10T13:38:00-05:00</updated>
<id>http://incandescent.github.com/blog/2011/02/10/jquery-mobile-with-backbone-dot-js-and-phonegap</id>
<content type="html"><![CDATA[<p>We’ve received a few requests about mobile app development in the past few weeks. We were looking for different options and wanted to use something which could be written once and used on different devices including iOS and Android. We found two solutions: one called <a href="http://www.appcelerator.com/products/titanium-mobile-application-development/">Titanium Mobile</a> and another one called <a href="http://www.phonegap.com">PhoneGap</a>. If you are wondering what the differences between them are, you can read more <a href="http://stackoverflow.com/questions/1482586/comparison-between-corona-phonegap-titanium">here</a>.</p>
<p>We decided to stick with PhoneGap for now mostly because it looked simpler to start with. PhoneGap provides a set of project templates and a common JavaScript API for building “native” mobile applications. It supports iOS, Android, Blackberry, Symbian, and Palm. The JavaScript API allows for interaction with the native API’s for things like contact management, camera, GPS and other.</p>
<p>In our previous projects we used a lot of JavaScript. Our code was structured around a great tool called <a href="http://documentcloud.github.com/backbone/">Backbone.js</a>. We also used a lot of jQuery. We wanted to bring this experience to our mobile solution and decided to give jQuery Mobile a try. As a proof of concept we created a simple project called <strong>Happy Pointer</strong>.</p>
<p><img src="http://incandescent.github.com/happypointer/images/menu.png" /></p>
<p>The app makes use of the data coming from awesome <a href="http://simplegeo.com">SimpleGeo</a> and it’s integrated with Google Maps. It basically searches for things near you. (it searches for coffee places by default).</p>
<p><img src="http://incandescent.github.com/happypointer/images/navigation.png" /></p>
<p>You can find the code for the app on github here: https://github.com/incandescent/happypointer or check the <a href="http://incandescent.github.com/happypointer">demo</a>. jQuery Mobile is very easy to learn. You don’t have to write any JavaScript to start with something simple. It comes with numerous useful widgets and components. In order to use them you have to add a “data-role” to your html elements. For example if you want to render a button you can do:</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='html'><span class='line'><span class="nt"><a</span> <span class="na">href=</span><span class="s">"index.html"</span> <span class="na">data-role=</span><span class="s">"button"</span><span class="nt">></span>Link button<span class="nt"></a></span>
</span></code></pre></td></tr></table></div></figure>
<p>or lets say you want a list:</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='html'><span class='line'><span class="nt"><ul</span> <span class="na">data-role=</span><span class="s">"listview"</span><span class="nt">></ul></pre></span>
</span></code></pre></td></tr></table></div></figure>
<p>Overall we think PhoneGap and jQuery Mobile are great solutions for people who already have experience with web technologies and don’t want to fight with Android or Cocoa Frameworks. We plan to write more about our experience with Backbone.js and more about our adventures with mobile development in the future so please stay tuned.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Using the Linode API for provisioning]]></title>
<link href="http://incandescent.github.com/blog/2011/01/04/using-the-linode-api-for-provisioning/"/>
<updated>2011-01-04T16:48:00-05:00</updated>
<id>http://incandescent.github.com/blog/2011/01/04/using-the-linode-api-for-provisioning</id>
<content type="html"><![CDATA[<p><a href="http://www.linode.com" title="Linode.com" target="_blank">Linode</a> is a great VPS/Cloud provider and we use it to run a development/testing machine and a production MongoDB server. It also has an easy to use REST <a href="http://www.linode.com/api/" title="Linode API" target="_blank">API</a> which, unlike Amazon EC2, requires only an access key and no complicated X509 configuration. There is a nice Ruby library for this API on github: <a href="https://github.com/rick/linode">https://github.com/rick/linode</a></p>
<p>We use Puppet to manage node configuration once a node is provisioned (and this is cloud-provider agnostic), however provisioning the node requires use of the particular cloud provider’s API and this is where the library above comes in. There are libraries like <a href="http://incubator.apache.org/libcloud/" title="libcloud" target="_blank">libcloud</a> that provide an abstraction layer that works with many cloud providers - using the Linode API directly made the most sense for us.</p>
<p>The Ruby Linode library above exposes the Linode API directly, and it is fairly low level (no model of the node, config, etc.). Since (re)provisioning requires successive interactions with the same Linode instance, as well as a notion of a static configuration which can be applied to the node, it’s nice to have a higher level model of the virtual machine. We created a small library which wraps the Linode API and adds a couple of abstractions. You can find it here on GitHub:</p>
<p><a href="https://github.com/incandescent/linode-utils">https://github.com/incandescent/linode-utils</a></p>
<p>This linode-utils gem provides a simple model of a Linode Machine, as well as a small Linode configuration DSL.</p>
<p>Machine operations:</p>
<ul>
<li>boot</li>
<li>reload</li>
<li>shutdown</li>
<li>get_disks</li>
<li>delete_disks</li>
<li>delete_non_swap_disks</li>
<li>delete_configs</li>
<li>used_disk_space</li>
<li>create_disk_from_stackscript</li>
<li>create_config</li>
<li>wait_for_job</li>
</ul>
<p>Here is how we (re)provision a Linode instance:</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>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">api</span> <span class="o">=</span> <span class="no">Linode</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:api_key</span> <span class="o">=></span> <span class="n">api_key</span><span class="p">,</span> <span class="ss">:username</span> <span class="o">=></span> <span class="n">username</span><span class="p">,</span> <span class="ss">:password</span> <span class="o">=></span> <span class="n">password</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="no">LinodeUtils</span><span class="o">::</span><span class="no">LOG</span><span class="o">.</span><span class="n">info</span> <span class="s2">"Looking for linode named '</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">'"</span>
</span><span class='line'>
</span><span class='line'><span class="no">LINODE</span> <span class="o">=</span> <span class="no">Machine</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">api</span><span class="p">,</span> <span class="nb">name</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="no">LinodeUtils</span><span class="o">::</span><span class="no">LOG</span><span class="o">.</span><span class="n">info</span> <span class="s2">"Current linode status: "</span> <span class="o">+</span> <span class="no">LINODE</span><span class="o">.</span><span class="n">linode</span><span class="o">.</span><span class="n">status</span><span class="o">.</span><span class="n">to_s</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="no">LINODE</span><span class="o">.</span><span class="n">linode</span><span class="o">.</span><span class="n">status</span> <span class="o">!=</span> <span class="no">Linode</span><span class="o">::</span><span class="no">TERMINATED</span>
</span><span class='line'> <span class="no">LINODE</span><span class="o">.</span><span class="n">shutdown</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="no">LinodeUtils</span><span class="o">::</span><span class="no">LOG</span><span class="o">.</span><span class="n">info</span> <span class="s2">"Deleting non-swap disks"</span>
</span><span class='line'><span class="no">LINODE</span><span class="o">.</span><span class="n">delete_non_swap_disks</span>
</span><span class='line'>
</span><span class='line'><span class="no">LinodeUtils</span><span class="o">::</span><span class="no">LOG</span><span class="o">.</span><span class="n">info</span> <span class="s2">"Deleting configs"</span>
</span><span class='line'><span class="no">LINODE</span><span class="o">.</span><span class="n">delete_configs</span>
</span><span class='line'>
</span><span class='line'><span class="n">root_disk_id</span> <span class="o">=</span> <span class="no">LINODE</span><span class="o">.</span><span class="n">create_disk_from_stackscript</span><span class="p">({</span>
</span><span class='line'> <span class="ss">:size</span> <span class="o">=></span> <span class="no">LinodeUtils</span><span class="o">::</span><span class="no">MAXIMUM_DISK_SIZE</span><span class="p">,</span>
</span><span class='line'> <span class="ss">:distro</span> <span class="o">=></span> <span class="no">DISTRO_LABEL</span><span class="p">,</span>
</span><span class='line'> <span class="ss">:stackscriptid</span> <span class="o">=></span> <span class="no">STACK_SCRIPT_ID</span><span class="p">,</span>
</span><span class='line'> <span class="c1"># stack script options</span>
</span><span class='line'> <span class="ss">:root_pub_key</span> <span class="o">=></span> <span class="n">pub_key</span><span class="p">,</span>
</span><span class='line'> <span class="ss">:fqdn</span> <span class="o">=></span> <span class="n">hostname</span>
</span><span class='line'><span class="p">})</span>
</span><span class='line'>
</span><span class='line'><span class="n">config_id</span> <span class="o">=</span> <span class="no">LINODE</span><span class="o">.</span><span class="n">create_config</span><span class="p">(</span><span class="no">KERNEL_LABEL</span><span class="p">,</span> <span class="n">root_disk_id</span><span class="p">)</span>
</span><span class='line'><span class="no">LinodeUtils</span><span class="o">::</span><span class="no">LOG</span><span class="o">.</span><span class="n">info</span> <span class="s2">"Booting Linode..."</span>
</span><span class='line'>
</span><span class='line'><span class="no">LINODE</span><span class="o">.</span><span class="n">boot</span><span class="p">(</span><span class="n">config_id</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>(this is the interesting bit; the full script is about twice as large but the rest is mostly setup and argument parsing)</p>
<p>There is also a small DSL for constructing the Linode “config”. Here is an 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>
<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">config</span> <span class="o">=</span> <span class="no">LinodeUtils</span><span class="o">::</span><span class="no">LinodeConfig</span><span class="o">.</span><span class="n">build</span> <span class="no">LinodeUtils</span><span class="o">.</span><span class="n">init_api</span> <span class="k">do</span>
</span><span class='line'> <span class="n">label</span> <span class="s2">"My favorite config"</span>
</span><span class='line'> <span class="n">kernel</span> <span class="sr">/Latest 2\.6 Paravirt(?!.*x86_64.*)/</span>
</span><span class='line'> <span class="n">comment</span> <span class="s2">"first comment"</span>
</span><span class='line'> <span class="n">disk</span> <span class="mi">0</span><span class="p">,</span> <span class="ss">:root_device</span> <span class="o">=></span> <span class="kp">true</span>
</span><span class='line'> <span class="n">comment</span> <span class="s2">"second comment"</span>
</span><span class='line'> <span class="n">disk</span> <span class="mi">1</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>After implementing this automation for Linode, I think we could probably easily move to another service. The basic steps are the same:</p></p>
<ol>
<li>provision an instance - this requires selecting or building an OS image, and ensuring a root SSH key is installed</li>
<li>install a first-boot script to perform config/bootstrapping (how this is implemented differs to some degree from service to service)</li>
<li>ssh as root to execute any commands required to finish bootstrapping (if you have a configuration server that is known to the bootstrapped node then this step can be eliminated)</li>
</ol>
<p>On that note, stay tuned for future posts on bootstrapping a node with Puppet+Git, how to use Hudson and a “stable branch” Git methodology for continuous integration with Rails, and our foray into CouchDB-based desktop apps.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Whizpage - closed beta launched!]]></title>
<link href="http://incandescent.github.com/blog/2010/12/04/whizpage-closed-beta-launched/"/>
<updated>2010-12-04T13:05:00-05:00</updated>
<id>http://incandescent.github.com/blog/2010/12/04/whizpage-closed-beta-launched</id>
<content type="html"><![CDATA[<p>Small businesses have it tough. They do not have the advantages of economies of scale that larger companies do, but are at the same time more reliant on word of mouth and personal networking to market their business. When it comes to a web presence, small business owners are often stuck in the realm between purchasing a pricey custom-built web site, or going it alone with a Do It Yourself tool and spending their time navigating the intricacies of web development and social media instead of running their business.</p>
<p>We think small business owners could use a no-hassle service which allows them to easily create a web presence integrated with popular social media outlets out of the box.</p>
<p>So with that said, we’ve launched the closed beta of our new product, <strong><a href="http://whizpage.biz" title="WhizPage - the simple way for small businesses to create a web presence">Whizpage</a></strong>!</p>
<iframe frameborder="0" height="225" src="http://player.vimeo.com/video/16628599" width="400"></iframe>
<p>If you are a small business owner, feel free to sign up and try it out. We are launching early and building features based on user feedback. We’d love to hear from you!</p>
]]></content>
</entry>
</feed>