-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
939 lines (666 loc) · 61.7 KB
/
atom.xml
File metadata and controls
939 lines (666 loc) · 61.7 KB
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Sobiwi Blog]]></title>
<link href="http://sobiwi.peterwongpp.com/atom.xml" rel="self"/>
<link href="http://sobiwi.peterwongpp.com/"/>
<updated>2012-03-17T01:58:14+08:00</updated>
<id>http://sobiwi.peterwongpp.com/</id>
<author>
<name><![CDATA[Sobiwi]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Bootstrap 2.0!]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/bootstrap-2-dot-0/"/>
<updated>2012-03-17T00:48:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/bootstrap-2-dot-0</id>
<content type="html"><![CDATA[<p>A few weeks ago, there are something new appeared - Twitter Bootstrap 2.0 and SimpleForm 2.0!</p>
<h2>Twitter Bootstrap</h2>
<p><a href="http://twitter.github.com/bootstrap" title="Twitter Bootstrap">Twitter Bootstrap</a></p>
<p>We were using Bootstrap 1.3 and it was pretty good. Although we did not do any customization, the interface was very clean and easy to read. Furthermore, there are built-in handy jQuery plugins such as tooltips, modals, and alert messages.</p>
<p>Starting from 2.0, there are a lot of minor changes which you may have a look on <a href="http://twitter.github.com/bootstrap/upgrading.html">http://twitter.github.com/bootstrap/upgrading.html</a>.</p>
<p>And during this migration, we not only changed to the new default 12-columns grid system, but also the fluid layout. You may resize your browser to see the responsive design!</p>
<h2>SimpleForm</h2>
<p><a href="http://github.com/plataformatec/simple_form" title="SimpleForm">SimpleForm</a></p>
<p>SimpleForm 2.0 has a lot of updates. It now has much more flexibility to mix and match with different designs. And it now supports Bootstrap 2.0 by default! It makes generating beautiful forms much easier!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Javascript Selection is Ready]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/javascript-selection-is-ready/"/>
<updated>2012-02-27T13:30:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/javascript-selection-is-ready</id>
<content type="html"><![CDATA[<p><img class="left" src="http://sobiwi.peterwongpp.com/images/posts/highlight_verses_demo1.png" width="450" title="Highlight Verses Demo 1" alt="Highlight Verses Demo 1">
<img class="left" src="http://sobiwi.peterwongpp.com/images/posts/highlight_verses_demo2.png" width="450" title="Highlight Verses Demo 2" alt="Highlight Verses Demo 2"></p>
<p>Finally the Javascript Selection plugin is ready now.</p>
<p>Now when you highlight verse on a chapter page (for example, highlighting the first two verses in Genesis chapter 1), you may see a black background on the highlighted words.</p>
<p>To highlight, simply mouse down on verse, do not release your mouse button and move your mouse around, and finally release your mouse button.</p>
<p>After releasing your mouse button, there should be a modal dialog pop up and your selection will be shown there. The next step will be let you add notes to the selection!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[updated the schedule]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/updated-the-schedule/"/>
<updated>2012-02-06T21:49:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/updated-the-schedule</id>
<content type="html"><![CDATA[<p>We just updated the schedule page to indicate the stage we are at :)</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Refactor is Important]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/refactor-is-important/"/>
<updated>2012-02-05T19:39:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/refactor-is-important</id>
<content type="html"><![CDATA[<p>This week a lot of refactorings have been done:</p>
<ul>
<li>form builder</li>
<li>highlighting notes on verses</li>
<li>layouts and partials</li>
</ul>
<!-- more -->
<h2>Form Builder</h2>
<p>As you may already known, Sobiwi is based on <a href="http://twitter.github.com/bootstrap">Bootstrap</a> framework. Bootstrap is releasing its 2.0 version currently. But we are still using the 1.4 version.</p>
<p>To make it worse, our forms are generated by dirty (non-reusable) code. There are currently 6 forms (registration, login / logout, forget password, reset password, user updating and church updating). And it is obvious that there would be more and more forms. In the future, if we decide to upgrade to Bootstrap 2.0, it would be a nightmare to modify every forms (it seems that the some css class names have been updated).</p>
<p>Now we do not have too many forms and the refactoring is worth doing. Now we have a <code>BootstrapFormBuilder</code> to use very clean and direct syntax to generate the form structure of Bootstrap 1.4 forms. More form builders could be implemented easily to match the new form structures such as the Inline and Horizontal forms.</p>
<h2>Highlighting Notes on Verses</h2>
<p>The wiki part (user-contributing content) is always the most difficult one. We planned to let the user highlight a portion of text with or across verse(s).</p>
<p>We have developed a jQuery plugin for our own use to highlight texts. That plugin’s code is ugly yet functional. Now we need to show the notes on the verses.</p>
<p>For example, there were several annotations (an annotation is note on a portion of verse). We need those annotations being shown as soon as the page is shown.</p>
<p>By the trail we did, it turned out the the current HTML markups are not flexible enough to handle that efficiently. What’s more it is confusing to use only one color to highlight the notes.</p>
<p>As a result, we need to re-structure the markups and thus update the plugin we mentioned before (this reveals a smell of code…).</p>
<p>Luckily, the refactor has been done and we now can continuse to implement the highlighting existing annotations functionality.</p>
<h2>Layouts and Partials</h2>
<p>Actually this part is still in progress and I suppose it would be done next week.</p>
<p>The layouts and partials are drawn on paper and made clear what’s their responsibily. Now they are clearer and view tests could be written.</p>
<p>It is in progress and we have updated some parts such as the different timelines (in a single verse, a user’s profile, user’s home, etc).</p>
<p>However, the Bootstrap 2.0 made me stop and think again should it be done now, or should it be done together with upgrading to Bootstrap 2.0.</p>
<p>If any of you have ideas for me, please tell me either though the contact us form, emails or twitter!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[user timeline]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/user-timeline/"/>
<updated>2012-01-30T14:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/user-timeline</id>
<content type="html"><![CDATA[<p><img class="right" src="http://sobiwi.peterwongpp.com/images/posts/user_timeline_demo.png" width="450" title="User Timeline Demo" alt="User Timeline Demo"></p>
<p>We are now implementing the Timeline - a time-ordered series of notes written by the user himself and the friends he is following.</p>
<p>The screen shot on the right hand side is an actual display from my testing account, which means the code is on the server and is running.</p>
<p>However, the functionality of adding notes is not yet ready for public. We must try our best to deploy it ASAP!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Newly Updates]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/newly-updates/"/>
<updated>2012-01-24T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/newly-updates</id>
<content type="html"><![CDATA[<p>After the interim presentation, I have been working on the wiki module which is for handling user contributed knowledges (has no any solid relation to the Wikipedia).</p>
<p>By the way, I am happy that the schedule was quite well and I actually have done 50% of the project! It is encouraging!</p>
<p>Back to the wiki module. What I have done in these two weeks are mainly on the timeline. The timeline is a series of notes created by the user himself as well as his friends (users he is following), ordered by the creation time.</p>
<p>So now it can be listed on the user homepage.</p>
<p>The coming tasks are:</p>
<ol>
<li>to add more note types support. Now for simplicity we just added two types: share of verse(s) and article on verse(s).</li>
<li>to build web interface for the users to manage their notes.</li>
</ol>
<p>However, it is unexpected that there are so many spams on this site! So I am planning to move out. This would take some time, but I am pretty sure it is worth doing.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Setup Cucumber]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/setup-cucumber/"/>
<updated>2011-12-25T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/setup-cucumber</id>
<content type="html"><![CDATA[<p>This post will show how to add cucumber (<a href="http://cukes.info" title="Cucumber">http://cukes.info</a>) support for acceptance testing. This is in addition to the previous post <a href="http://sobiwi.peterwongpp.com/blog/setup-the-test-environment">Setup the Test Environment</a>.</p>
<p>We are going to install cucumber, as well as adding support for spork and guard in order to load cucumber features faster.</p>
<p>Finally, don’t forget the simplecov. It supports both rspec and cucumber :)</p>
<!-- more -->
<h2>Code</h2>
<h3>1) Install cucumber</h3>
<p>add this to the Gemfile and the run <code>bundle</code>:</p>
<figure class='code'><figcaption><span>Gemfile</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='ruby'><span class='line'><span class="n">group</span> <span class="ss">:test</span> <span class="k">do</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'cucumber-rails'</span>
</span><span class='line'> <span class="c1"># database_cleaner is not required, but highly recommended</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'database_cleaner'</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>after the bundle command finished, run the generator:</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='sh'><span class='line'>rails generate cucumber:install
</span></code></pre></td></tr></table></div></figure>
<p>Now, you may run cucumber by running this command:</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='sh'><span class='line'>cucumber features
</span><span class='line'><span class="c"># or</span>
</span><span class='line'>rake cucumber
</span></code></pre></td></tr></table></div></figure>
<h3>2) Spork support for cucumber</h3>
<p>Still remember how did we add spork support for rspec? We ran <code>spork --bootstrap</code>. However, if we run the same command again, it should only work for rspec. For cucumber, we do the following:</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='sh'><span class='line'>spork cucumber --bootstrap
</span></code></pre></td></tr></table></div></figure>
<p>To start a spork for rspec, we run <code>spork</code>. For cucumber, we need:</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='sh'><span class='line'>spork cucumber
</span></code></pre></td></tr></table></div></figure>
<p>Now, before we actually run the spork command, let’s update the features/support/env.rb so that spork loads correctly. The instructions of how to update the env.rb have been added to the env.rb file when you run <code>spork cucumber --bootstrap</code>.</p>
<p>To use spork with cucumber, run these in two consoles:</p>
<figure class='code'><figcaption><span>console 1</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='sh'><span class='line'>spork cucumber
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>console 2</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='sh'><span class='line'>cucumber --drb features
</span></code></pre></td></tr></table></div></figure>
<h3>3) Guard cucumber</h3>
<p>add this to Gemfile and run <code>bundle</code></p>
<figure class='code'><figcaption><span>Gemfile</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">group</span> <span class="ss">:test</span> <span class="k">do</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'guard-cucumber'</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>after that, run:</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='sh'><span class='line'>guard init cucumber
</span></code></pre></td></tr></table></div></figure>
<p>The update have been added to the Guardfile. You may have a look to see if you need any customization. But for me it’s OK already :)</p>
<p>Now <code>guard</code> command will run both cucumber and rspec in the same time.</p>
<h3>4) simplecov</h3>
<p>add this single line to the top of the features/support/env.rb:</p>
<figure class='code'><figcaption><span>top of features/support/env.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">'simplecov'</span>
</span><span class='line'><span class="c1"># ... rest of the file</span>
</span></code></pre></td></tr></table></div></figure>
<p>To generate coverage report, same as the rspec, just directly run <code>cucumber features</code> instead of running cucumber from guard.</p>
<p>Now, all are done :)</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[User Authentication]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/user-authentication/"/>
<updated>2011-12-16T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/user-authentication</id>
<content type="html"><![CDATA[<p>There are a bunch of well developed user authentication gems available for rails. One of them is <a href="http://www.omniauth.org">OmniAuth</a>.</p>
<p>Starting from version 1.x, OmniAuth separated every strategies into separated gems. OmniAuth integrated many different authentication providers, such as Facebook, Twitter, OpenId, in order to provide a standardized interface.</p>
<p>Each provider is a so-called strategy. Recently there is a omniauth-identity gem to due with the traditional username password authentication instead of using external providers.</p>
<p>In short, making use of OmniAuth, we could provide username password authentication with the omniauth-identity, while having an advantage of integrate with other external providers relatively easier.</p>
<!-- more -->
<h2>Code</h2>
<p>I am going to follow the episode <a href="http://railscasts.com/episodes/304-omniauth-identity">#304 OmniAuth Identity</a> with little modifications to suit our need.</p>
<h3>1) add the following to the Gemfile and run <code>bundle</code></h3>
<figure class='code'><figcaption><span>Gemfile</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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="s1">'bcrypt-ruby'</span><span class="p">,</span> <span class="s1">'~> 3.0.0'</span>
</span><span class='line'><span class="n">gem</span> <span class="s1">'omniauth-identity'</span>
</span></code></pre></td></tr></table></div></figure>
<h3>2) create a config/initializers/omniauth.rb file with the following content:</h3>
<figure class='code'><figcaption><span>config/initializers/omniauth.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">Rails</span><span class="o">.</span><span class="n">application</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">middleware</span><span class="o">.</span><span class="n">use</span> <span class="no">OmniAuth</span><span class="o">::</span><span class="no">Builder</span> <span class="k">do</span>
</span><span class='line'> <span class="n">provider</span> <span class="ss">:identity</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h3>3) create the sessions_controller for handling sign in / out for omniauth</h3>
<p>run the following command: <code>rails generate controller sessions</code></p>
<p>edit the generated app/controllers/sessions_controller.rb file as:</p>
<figure class='code'><figcaption><span>app/controllers/sessions_controller.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="k">class</span> <span class="nc">SessionsController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">new</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">create</span>
</span><span class='line'> <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="o">.</span><span class="n">from_omniauth</span><span class="p">(</span><span class="n">env</span><span class="o">[</span><span class="s2">"omniauth.auth"</span><span class="o">]</span><span class="p">)</span>
</span><span class='line'> <span class="n">session</span><span class="o">[</span><span class="ss">:user_id</span><span class="o">]</span> <span class="o">=</span> <span class="n">user</span><span class="o">.</span><span class="n">id</span>
</span><span class='line'> <span class="n">redirect_to</span> <span class="n">root_url</span><span class="p">,</span> <span class="n">notice</span><span class="p">:</span> <span class="s2">"Signed in!"</span><span class="p">;</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">destroy</span>
</span><span class='line'> <span class="n">session</span><span class="o">[</span><span class="ss">:user_id</span><span class="o">]</span> <span class="o">=</span> <span class="kp">nil</span>
</span><span class='line'> <span class="n">redirect_to</span> <span class="n">root_url</span><span class="p">,</span> <span class="n">notice</span><span class="p">:</span> <span class="s2">"Signed out!"</span><span class="p">;</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">failure</span>
</span><span class='line'> <span class="n">redirect_to</span> <span class="n">root_url</span><span class="p">,</span> <span class="n">alert</span><span class="p">:</span> <span class="s2">"Authentication failed, please try again."</span><span class="p">;</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>Now you could see there are something we do not have right now: User model and root_url</p>
<h3>4) create the User model</h3>
<p>by using the following command:</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='sh'><span class='line'>rails generate model user provider:string uid:string display_name:string <span class="c"># any other fields you might want</span>
</span></code></pre></td></tr></table></div></figure>
<p>followed by <code>rake db:migrate</code></p>
<p>and then update the generated app/models/user.rb as:</p>
<figure class='code'><figcaption><span>app/models/user.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">User</span> <span class="o"><</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
</span><span class='line'> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">from_omniauth</span><span class="p">(</span><span class="n">auth</span><span class="p">)</span>
</span><span class='line'> <span class="n">find_by_provider_and_uid</span><span class="p">(</span><span class="n">auth</span><span class="o">[</span><span class="s2">"provider"</span><span class="o">]</span><span class="p">,</span> <span class="n">auth</span><span class="o">[</span><span class="s2">"uid"</span><span class="o">]</span><span class="p">)</span> <span class="o">||</span> <span class="n">create_with_omniauth</span><span class="p">(</span><span class="n">auth</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">create_with_omniauth</span><span class="p">(</span><span class="n">auth</span><span class="p">)</span>
</span><span class='line'> <span class="n">create!</span> <span class="k">do</span> <span class="o">|</span><span class="n">user</span><span class="o">|</span>
</span><span class='line'> <span class="n">user</span><span class="o">.</span><span class="n">provider</span> <span class="o">=</span> <span class="n">auth</span><span class="o">[</span><span class="s2">"provider"</span><span class="o">]</span>
</span><span class='line'> <span class="n">user</span><span class="o">.</span><span class="n">uid</span> <span class="o">=</span> <span class="n">auth</span><span class="o">[</span><span class="s2">"uid"</span><span class="o">]</span>
</span><span class='line'> <span class="n">user</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">auth</span><span class="o">[</span><span class="s2">"info"</span><span class="o">][</span><span class="s2">"name"</span><span class="o">]</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>Now the User model part is ready. It’s time to the identity part. In omniauth-identity, there is another model for handling the authentication instead of the user model (of course you may map the model in the config…).</p>
<h3>5) create the Identity model</h3>
<p>by using the following command:</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='sh'><span class='line'>rails generate model identity name:string email:string password_digest:string
</span></code></pre></td></tr></table></div></figure>
<p>followed by <code>rake db:migrate</code></p>
<p>Now you need to update the generated app/models/identity.rb as:</p>
<figure class='code'><figcaption><span>app/models/identity.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Identity</span> <span class="o"><</span> <span class="no">OmniAuth</span><span class="o">::</span><span class="no">Identity</span><span class="o">::</span><span class="no">Models</span><span class="o">::</span><span class="no">ActiveRecord</span>
</span><span class='line'> <span class="c1"># anything else you want</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h3>6) add the following two paths to suitable position in your view file:</h3>
<p>6.1) create identity path: /auth/identity/register<br/>
6.2) login path: /auth/identity</p>
<p>The above 2 links are linked to the default registration and login pages. However, these 2 default pages does not match our design as well as there are no error handling. So we need to provide validations to Identity model and also provide the registration and login pages.</p>
<h3>7) insert validation rules to the identity model</h3>
<figure class='code'><figcaption><span>app/models/identity.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="n">presence</span><span class="p">:</span> <span class="kp">true</span>
</span><span class='line'><span class="n">validates</span> <span class="ss">:email</span><span class="p">,</span> <span class="n">uniqueness</span><span class="p">:</span> <span class="kp">true</span><span class="p">,</span> <span class="nb">format</span><span class="p">:</span><span class="sr"> /^[^@\s]+\@([-a-z0-9]+\.)+[a-z0-9]{2</span>
</span></code></pre></td></tr></table></div></figure>
<p>We do not need to add <code>presence: true</code> to the email validation as the format do not allow blank input.</p>
<h3>8 ) points for the login form</h3>
<p>I am not going to paste my full code in both the login form as well as the registration form as it would be too long.</p>
<p>Instead, I write down the things we need to notice here.</p>
<p>8.1) you should be using form_tag and must post to /auth/identity/callback<br/>
8.2) these two fields should present: auth_key (for email) and password<br/>
8.3) the above 2 keys should be in top level in params.</p>
<p>For example <code><%= text_field_tag :auth_key %></code><br/>
Instead of <code><%= text_field_tag :login[auth_key] %></code></p>
<p>If you actually using form_for, You could do: <code><%= f.text_field :auth_key, name: "auth_key" %></code></p>
<p>8.4) I would recommend to put the form inside the sessions#new view. This view file in the future will also provide other external providers’ login.</p>
<p>That’s all for login form :)</p>
<h3>9) points for the registration form</h3>
<p>9.1) you should create a identities_controller and using at least the new action. (no need to use create action as the registration form is actually passed to omniauth for the standardized approach).<br/>
9.2) put the needed route into the routes.rb file. eg. <code>resources :identities, only: [:new]</code><br/>
9.3) you should again be using form_tag and must post to /auth/identity/register<br/>
9.4) by default, only the following fields will be handled: <code>name</code>, <code>email</code>, <code>password</code>, <code>password_confirmation</code>.<br/>
<code>password</code> and <code>password_confirmation</code> must be handle, while <code>name</code> and <code>email</code> could be set in the configuration. To change <code>name</code>, <code>email</code> or to add more other fields, you should update the following line in the config/initializers/omniauth.rb as the next code block.<br/>
9.5) you need also to make omniauth-identity to redirect back to the identities#new, see the next code block too.</p>
<figure class='code'><figcaption><span>config/initializers/omniauth.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">provider</span> <span class="ss">:identity</span><span class="p">,</span> <span class="ss">:fields</span> <span class="o">=></span> <span class="o">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:email</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'> <span class="n">on_failed_registration</span><span class="p">:</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="o">|</span><span class="n">env</span><span class="o">|</span>
</span><span class='line'> <span class="no">IdentitiesController</span><span class="o">.</span><span class="n">action</span><span class="p">(</span><span class="ss">:new</span><span class="p">)</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>9.6) define the identities#new action as follow:</p>
<figure class='code'><figcaption><span>app/controllers/identities_controller.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">new</span>
</span><span class='line'> <span class="vi">@identity</span> <span class="o">=</span> <span class="n">env</span><span class="o">[</span><span class="s1">'omniauth.identity'</span><span class="o">]</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h3>10) add the required routes</h3>
<figure class='code'><figcaption><span>config/routes.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">get</span> <span class="s1">'/login'</span> <span class="o">=></span> <span class="s1">'sessions#new'</span><span class="p">,</span> <span class="n">as</span><span class="p">:</span> <span class="ss">:login</span>
</span><span class='line'><span class="n">match</span> <span class="s1">'/auth/:provider/callback'</span><span class="p">,</span> <span class="n">to</span><span class="p">:</span> <span class="s1">'sessions#create'</span>
</span><span class='line'><span class="n">match</span> <span class="s1">'/auth/failure'</span><span class="p">,</span> <span class="n">to</span><span class="p">:</span> <span class="s1">'sessions#failure'</span>
</span><span class='line'><span class="n">match</span> <span class="s1">'/logout'</span><span class="p">,</span> <span class="n">to</span><span class="p">:</span> <span class="s1">'sessions#destroy'</span><span class="p">,</span> <span class="ss">:as</span> <span class="o">=></span> <span class="ss">:logout</span>
</span><span class='line'>
</span><span class='line'><span class="n">resources</span> <span class="ss">:identities</span><span class="p">,</span> <span class="n">only</span><span class="p">:</span> <span class="o">[</span><span class="ss">:new</span><span class="o">]</span> <span class="c1"># as well as the route for the registration form</span>
</span></code></pre></td></tr></table></div></figure>
<p>All things should be done :)</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Setup the Test Environment]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/setup-the-test-environment/"/>
<updated>2011-12-12T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/setup-the-test-environment</id>
<content type="html"><![CDATA[<p>There are some gems for specific parts of testing.</p>
<p><a href="http://github.com/thoughtbot/factory_girl" title="FactoryGirl">factory_girl</a> - for generating fixtures</p>
<p><a href="http://www.relishapp.com/rspec" title="RSpec 2">rspec2</a> - for doing unit test, integration test, etc</p>
<p><a href="http://github.com/jnicklas/capybara" title="Capybara">capabara</a> - for mimicking user’s behaviour in order to do user acceptance test and improviding the integration test</p>
<p><a href="http://github.com/sporkrb/spork" title="Spork">spork</a> - to fork a test environment before each run of the tests, for firing test cases much faster than the traditional way which loads the entire rails test environment before you could run the test cases</p>
<p><a href="http://github.com/guard/guard" title="Guard">guard</a> - for handling events on file modifications. It is configured that whenever a source code or a test case is updated, the corresponding test cases would be run automatically. Together with spork, test cases would be automatically run in a fast pace whenever a source code or a test case is updated so that we could get the test result in real time</p>
<p><a href="http://github.com/colszowka/simplecov" title="SimpleCov">simplecov</a> - for code coverage report generation</p>
<!-- more -->
<h2>Code</h2>
<figure class='code'><figcaption><span>Gemfile</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='text'><span class='line'>group :test, :development do
</span><span class='line'> gem 'rspec-rails', '~> 2.6'
</span><span class='line'> gem 'factory_girl_rails'
</span><span class='line'>end
</span><span class='line'>
</span><span class='line'>group :test do
</span><span class='line'> gem 'spork', '~> 0.9.0.rc'
</span><span class='line'>
</span><span class='line'> gem 'guard-rspec'
</span><span class='line'> gem 'guard-spork'
</span><span class='line'>
</span><span class='line'> gem 'capybara'
</span><span class='line'>
</span><span class='line'> gem 'simplecov', :require => false
</span><span class='line'>end
</span></code></pre></td></tr></table></div></figure>
<p>then run <code>bundle</code></p>
<p>init rspec:</p>
<figure class='code'><figcaption><span>console</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='text'><span class='line'>rails generate rspec:install
</span><span class='line'>> create .rspec
</span><span class='line'>> create spec
</span><span class='line'>> create spec/spec_helper.rb
</span></code></pre></td></tr></table></div></figure>
<p>setup spork:</p>
<figure class='code'><figcaption><span>console</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='text'><span class='line'>spork --bootstrap
</span></code></pre></td></tr></table></div></figure>
<p>after that, some instructions are inserted into spec/spec_helper.rb automatically. Update the spec/spec_helper.rb file according to the instructions.</p>
<p>now, is time to guard rspec.</p>
<figure class='code'><figcaption><span>console</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='text'><span class='line'>guard init rspec
</span><span class='line'>> Writing new Guardfile to /Users/PeterWong/Projects/sobiwi/Guardfile
</span><span class='line'>> rspec guard added to Guardfile, feel free to edit it
</span></code></pre></td></tr></table></div></figure>
<p>then is to guard spork:</p>
<figure class='code'><figcaption><span>console</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>
</pre></td><td class='code'><pre><code class='text'><span class='line'>guard init spork
</span><span class='line'>> spork guard added to Guardfile, feel free to edit it
</span></code></pre></td></tr></table></div></figure>
<p>now we need to update the Guardfile to move the newly appended <code>guard 'spork'</code> block to the top of the <code>guard 'rspec'</code> block.</p>
<p>Also we need to do the following:</p>
<figure class='code'><figcaption><span>Guardfile</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="c1"># change the following line</span>
</span><span class='line'><span class="n">guard</span> <span class="s1">'rspec'</span><span class="p">,</span> <span class="ss">:version</span> <span class="o">=></span> <span class="mi">2</span> <span class="k">do</span>
</span><span class='line'><span class="c1"># to</span>
</span><span class='line'><span class="n">guard</span> <span class="s1">'rspec'</span><span class="p">,</span> <span class="ss">:version</span> <span class="o">=></span> <span class="mi">2</span><span class="p">,</span> <span class="ss">:cli</span> <span class="o">=></span> <span class="s1">'--drb'</span> <span class="k">do</span>
</span></code></pre></td></tr></table></div></figure>
<p>now guard is working and to run test cases in real time, run the command <code>guard</code>.</p>
<p>to setup capybara, update:</p>
<figure class='code'><figcaption><span>rails spec/spec_helper.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">ENV</span><span class="o">[</span><span class="s2">"RAILS_ENV"</span><span class="o">]</span> <span class="o">||=</span> <span class="s1">'test'</span>
</span><span class='line'><span class="nb">require</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s2">"../../config/environment"</span><span class="p">,</span> <span class="bp">__FILE__</span><span class="p">)</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">'rspec/rails'</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">'rspec/autorun'</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">'capybara/rspec'</span> <span class="c1"># add this new line</span>
</span></code></pre></td></tr></table></div></figure>
<p>finally to automatically reload factory_girl fixtures, add the following line inside the <code>Spork.each_run</code> block in the spec/spec_helper.rb:</p>
<figure class='code'><figcaption><span>spec/spec_helper.rb</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="no">FactoryGirl</span><span class="o">.</span><span class="n">reload</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now things are all done. We could do TDD too :)</p>
<p>Oh, forgot to setup the simeplecov. To set it up, insert the following line in the very beginning of the spec/spec_helper.rb file:</p>
<figure class='code'><figcaption><span>spec/spec_helper.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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">'simplecov'</span>
</span><span class='line'><span class="o">.</span><span class="n">.</span><span class="o">.</span> <span class="c1"># rest of the original file content</span>
</span></code></pre></td></tr></table></div></figure>
<p>and then create a .simplecov file in the root of the project having the following content:</p>
<figure class='code'><figcaption><span>.simplecov</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='ruby'><span class='line'><span class="no">SimpleCov</span><span class="o">.</span><span class="n">start</span> <span class="s1">'rails'</span> <span class="k">do</span>
</span><span class='line'> <span class="n">add_filter</span> <span class="s1">'spec'</span>
</span><span class='line'>
</span><span class='line'> <span class="n">add_group</span> <span class="s1">'Mailers'</span><span class="p">,</span> <span class="s1">'app/mailers'</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>It is to tell simplecov to ignore the code coverage of the spec directory (we do not test out test cases) and add a group named Mailers for the mailers in case we have mailers in use.</p>
<p><code>SimpleCov.start 'rails'</code> will automatically group controllers, helpers, models, lib and plugins code and so those groups do not need to be added by ourself.</p>
<p>One more note, to obtain the coverage report, guard cannot be used. Instead we should run rspec directly:</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">rspec</span> <span class="o">.</span>
</span></code></pre></td></tr></table></div></figure>
<p>to run all the spec to obtain the full coverage report (as the hits per line etc need to be calculated, we must ensure every test case is run once).</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Server Setup for both production and development environments]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/server-setup-for-both-production-and-development-environments/"/>
<updated>2011-12-11T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/server-setup-for-both-production-and-development-environments</id>
<content type="html"><![CDATA[<h2>Introduction</h2>
<p>As decided, we are going to use <a href="http://rubyonrails.org">Ruby on Rails</a>, a MVC web framework written in Ruby language.</p>
<p>The main development environment will be a Mac OS X version 10.7, while the main production environment will be on <a href="http://heroku.com">Heroku</a>, a cloud application platform.</p>
<p>On both the environments, we are going to use <a href="http://code.macournoyer.com/thin">Thin</a> as the web server, and use the MySQL database with mysql2 gem as an adapter for rails.</p>
<p>It should be noted that the MySQL database on the production environment is a fault tolerant database-as-a-service in the cloud. The service is named <a href="http://cleardb.com">ClearDB</a>. There is an add-on on heroku and a free service is choosable although it is in a lower power: 5MB storage, 10 Connections, Low I/O Performance and Daily Backups.</p>
<p>As in the current state, we are on developing or testing state, 1 dyno in heroku with the free add-on of ClearDB should be enough.</p>
<p>Now, back to the code.</p>
<!-- more -->
<h2>Code</h2>
<p>First, add the following to the Gemfile and then run <code>bundle install</code>:</p>
<figure class='code'><figcaption><span>Gemfile</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='ruby'><span class='line'><span class="c1"># Original gems for a rails 3 app:</span>
</span><span class='line'><span class="n">gem</span> <span class="s1">'rails'</span><span class="p">,</span> <span class="s1">'3.1.3'</span>
</span><span class='line'>
</span><span class='line'><span class="n">group</span> <span class="ss">:assets</span> <span class="k">do</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'sass-rails'</span><span class="p">,</span> <span class="s1">'~> 3.1.5'</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'coffee-rails'</span><span class="p">,</span> <span class="s1">'~> 3.1.1'</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'uglifier'</span><span class="p">,</span> <span class="s1">'>= 1.0.3'</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">gem</span> <span class="s1">'jquery-rails'</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Newly added gems:</span>
</span><span class='line'><span class="n">gem</span> <span class="s1">'thin'</span> <span class="c1"># http://code.macournoyer.com/thin</span>
</span><span class='line'><span class="n">gem</span> <span class="s1">'mysql2'</span>
</span><span class='line'><span class="n">gem</span> <span class="s1">'foreman'</span> <span class="c1"># https://github.com/ddollar/foreman</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now, create a Procfile in the root of the application:</p>
<figure class='code'><figcaption><span>Procfile</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='text'><span class='line'>web: bundle exec rails server thin -p $PORT
</span></code></pre></td></tr></table></div></figure>
<p>Finally to start up the web process, run the following command:</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='sh'><span class='line'>foreman start
</span></code></pre></td></tr></table></div></figure>
<h2>Explanations</h2>
<p>As we discussed above, the thin is the web server and the mysql2 is the database adapter for rails.</p>
<p>We are going to use rails 3.1. The minor version might be updated for more functionality support or security issues. Rails 3.1 comes with Asset Pipeline which makes CSS and Javascript a first-class citizen in Rails. Those gems in the asset group are for the asset pipeline. And the jquery-rails gem is to use jQuery as the default Javascript library to be used in the project.</p>
<p>Finally, the foreman is a gem for managing Procfile-based applications. It automatically starts up the processes written in a Procfile in a certain format. Heroku supports Procfile and thus it is convenient to manage the processes required by the application with the help of Procfile.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Changing Direction]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/changing-direction/"/>
<updated>2011-12-03T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/changing-direction</id>
<content type="html"><![CDATA[<p>These few weeks doing less actual coding work. Instead, much more on thinking.</p>
<p>After the recent meeting with Dr. Lau, the supervisor, new directions are coming up.</p>
<p>Bible wiki, is the original main idea of the project. However, social, bible and wiki are just all tools. Why do we need such a bible wiki? Is the bible wiki useful?</p>
<p>For example, I was doubting if notes could be added to the verses only, or to verses, chapters, books, testaments, or even different versions of bibles. The current implementation is the later one, which is able to add things to every thing in a bible! However, is that really useful? Now I am planning to change. Instead of having 30k records of verses, belonging to different chapters, belongings to different books, then testaments and finally one bible, using a compound key of [bible, book name, chapter, verser] should be better! It may be kind of denormalization, but this make the queries a lot simpler.</p>
<p>It’s better to do more research than writing notes here :) See you later</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Recent Updates Again]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/recent-updates-again/"/>
<updated>2011-10-25T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/recent-updates-again</id>
<content type="html"><![CDATA[<p>Reading week and mid-term examinations are really time killer :) Finally we are back to the development now.</p>
<p>Before the recent updates, I would like to thank Roy Huesman for his comment on the FYP homepage. It reminds me that there are really someone viewing the site! I admit that the theme I created before is actually functionally-incomplete. Instead of completing the functionalities and beautify the layout, I decided to use an open source theme.</p>
<p>Now the recent updates of the application.</p>
<p>Apart from the layout updates, we have implemented the test environment. Some test have been set up and passed. More test cases will be written when the features are being implemented later.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Recent Updates]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/recent-updates/"/>
<updated>2011-10-09T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/recent-updates</id>
<content type="html"><![CDATA[<p>These days were busying on the actual coding work of the application.</p>
<p>The application has been pushed to Heroku and is running with PostreSQL database in production server (SQLite in development and test environments).</p>
<p>In the last news, we mentioned that the bibles were imported already. Actually after that we have done some minor updates on the process, so that the meta data together with each bible are more useful and the import speed is a lot faster.</p>
<p>In the recent updates, we have implemented a basic front end showing the bible contents. So it is now a viewable, clean and clear online bible with multi-lingual supports! (We are going to provide English and Traditional Chinese versions only, although adding more locales are as easy as simply translating a static file)</p>
<p>A basic membership system is built also. Any visitor can register as a member, with only a username and a password. After he is signed in, we will record down his locale and the bible version he is reading so that when he sign in next time, we could show the most suitable content to him.</p>
<p>Now, we are writing automated tests on the parts we have done currently and will refactor the code if needed. By this way, we have tests to confirm that we do not break the current functionalities in the development, and we have clean code to work on.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Bibles Imported!]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/bibles-imported/"/>
<updated>2011-10-03T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/bibles-imported</id>
<content type="html"><![CDATA[<p>Yesterday night, we have finally uploaded the whole bible content into our application, including a Traditional Chinese version (和合本) and an English version (KJV), which used us about 2211460 seconds (about 36 ~ 37 minutes) for converting the downloaded format into a self-defined format and importing the bible in self-defined format into our database using ActiveRecord.</p>
<p>We parse the self-defined format line by line. Each line represents an object (a row in the database). We create the object line by line and that’s why the slowness of the import.</p>
<p>The good news is we now have a self-defined format of the representation of bible in plain text. Importing more versions of bibles would be as easy as a cake.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Database Design]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/database-design/"/>
<updated>2011-10-01T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/database-design</id>
<content type="html"><![CDATA[<p>This week the database structure design has been finished.</p>
<p>The tables can be separated mainly into 3 parts: bible content part, social networking part and the wiki part.</p>
<p>The bible content part is the table for storing localized contents of bibles. As we all know, there are so many versions of bibles translated into hundreds of languages. We would like to add more versions of bibles in the future easily, so the bibles are stored into the database instead of statically.</p>
<p>The social networking part stores the users data and the virtual churches. User-user and user-virtual-church relationships are the basic building blocks in this part.</p>
<p>The wiki part stores the users’ contributions, such as photos they uploaded, notes they wrote. Every thing created by the user could be set to private, friend-only (including other people in the same virtual churches), and public.</p>
<p>More tables can be added in the future if needed easily as the database is designed very clean and simple.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Production Environment]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/production-environment/"/>
<updated>2011-09-26T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/production-environment</id>
<content type="html"><![CDATA[<p>As written in the schedule, 30th September 2011 is the due date to finalize the production for our web server.</p>
<p>We originally planned to host our web server by using the virtual machine provided by the FYP course. However, it costs HKD$700 while we were given HKD$1,000 virtual dollars (A FYP team receives HKD$1,000 per team member).</p>
<p>As a result, we decided to use a PaaS (Platform as a Service) cloud service to be our host. It is named <a href="http://heroku.com" title="Heroku">Heroku</a>, which supports Ruby on Rails, and a bunch of other programs such as Node.js and Java.</p>
<p>It provides also a number of useful add-ons such as cron jobs, emails, custom domains.</p>
<p>Another update is the database we wil use. We planned to use MySQL. However using MySQL database in Heroku is not free. So we will change to PostgreSQL, which is free and the size is enough for our development.</p>
<p>We choose Heroku because it is fast and stable. Moreover it supports Git, which we are going to use for source version controlling. The development would be simplified a lot! And most importantly, the applications hosted on Heroku scales easily. In case we have too many users for acceptance tests or in production state, we could easily scale out to have more Web Dynos (A web dyno is a single web process running the code and responding to HTTP requests), or to upgrade the database.</p>
<p>The next step we have to do is to buy a domain name for our service, and setup the project on Heroku!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[2011.09.24 (Sat)]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/2011-09-24-sat/"/>
<updated>2011-09-24T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/2011-09-24-sat</id>
<content type="html"><![CDATA[<p>Our project website was originally written in pure PHP without any database.</p>
<p>I do not sure if it is my problem or not, but the uploading speed to the server through FTP was too slow that updating was extremely inconvenient.</p>
<p>As a result, <a href="http://wordpress.org" title="Wordpress">Wordpress</a> is used to build the project website using MySQL. A simple wordpress theme is created for the site.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[2011.09.23 (Fri)]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/2011-09-23-fri/"/>
<updated>2011-09-24T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/2011-09-23-fri</id>
<content type="html"><![CDATA[<p>A detailed schedule including the development stages and deliverables has been updated!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[2011.09.21 (Wed)]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/2011-09-21-wed/"/>
<updated>2011-09-24T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/2011-09-21-wed</id>
<content type="html"><![CDATA[<p>Updated the back end coding so that adding new pages would be a lot easier! (by making use of .htaccess to centralize the routing)</p>
<p>More on the project’s details will be uploaded soon.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[2011.09.15 (Thu)]]></title>
<link href="http://sobiwi.peterwongpp.com/blog/2011-09-15-thu/"/>
<updated>2011-09-24T00:00:00+08:00</updated>
<id>http://sobiwi.peterwongpp.com/blog/2011-09-15-thu</id>
<content type="html"><![CDATA[<p>The first draft of the project web page uploaded :)</p>
]]></content>
</entry>
</feed>