-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
1413 lines (1018 loc) · 96.3 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
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[黃金俠]]></title>
<link href="http://rubyist.marsz.tw/atom.xml" rel="self"/>
<link href="http://rubyist.marsz.tw/"/>
<updated>2013-06-11T10:10:46+08:00</updated>
<id>http://rubyist.marsz.tw/</id>
<author>
<name><![CDATA[MarsZ]]></name>
<email><![CDATA[[email protected]]]></email>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[透過 sidekiq 實作背景工作 (background job)]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-06-08/sidekiq/"/>
<updated>2013-06-08T15:08:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-06-08/sidekiq</id>
<content type="html"><![CDATA[<p><code>sidekiq</code> 是一套可以用來實作 background job 的 gem<br/>
舉凡長時間的執行如 email, 點數計算等等非即時性的工作, 都可以採用非同步執行<br/>
以加速前端服務的反應速度或減低主機負荷<br/>
和 <code>resque</code> 一樣,<code>sidekiq</code> 是以 redis 做為 <code>Message Queue</code> 來運作…</p>
<!-- more -->
<h3>安裝</h3>
<p>本教學所使用的版本是 2.12.1</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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="s2">"sidekiq"</span><span class="p">,</span> <span class="s2">"~> 2.12.1"</span>
</span></code></pre></td></tr></table></div></figure>
<p>設定 redis<br/>
關於 redis 安裝可參考 <a href="http://pm.5fpro.com/projects/public-wiki/wiki/Redis" target="_blank">http://pm.5fpro.com/projects/public-wiki/wiki/Redis</a></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='ruby'><span class='line'><span class="no">Sidekiq</span><span class="o">.</span><span class="n">configure_server</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">redis</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">:url</span> <span class="o">=></span> <span class="s2">"redis://127.0.0.1:6379/0"</span> <span class="p">}</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="no">Sidekiq</span><span class="o">.</span><span class="n">configure_client</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">redis</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">:url</span> <span class="o">=></span> <span class="s2">"redis://127.0.0.1:6379/0"</span> <span class="p">}</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h3>使用 (定義 worker)</h3>
<p>定義 worker</p>
<figure class='code'><figcaption><span>foo_worker.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">FooWorker</span>
</span><span class='line'> <span class="kp">include</span> <span class="no">Sidekiq</span><span class="o">::</span><span class="no">Worker</span>
</span><span class='line'> <span class="n">sidekiq_options</span> <span class="ss">:queue</span> <span class="o">=></span> <span class="ss">:barbar_queue</span><span class="p">,</span> <span class="ss">:retry</span> <span class="o">=></span> <span class="kp">false</span><span class="p">,</span> <span class="ss">:backtrace</span> <span class="o">=></span> <span class="kp">true</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">perform</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">count</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>啟動 worker (-c 代表 concurrency worker 數)</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">bundle</span> <span class="nb">exec</span> <span class="n">sidekiq</span> <span class="o">-</span><span class="n">c</span> <span class="mi">1</span>
</span></code></pre></td></tr></table></div></figure>
<p>把工作丟到 queue 裡</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="no">FooWorker</span><span class="o">.</span><span class="n">perform_async</span><span class="p">(</span><span class="s2">"haha"</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>這時若有啟動 worker 就會從 redis 把工作抓下來執行</p>
<h3>使用 (delay methods)</h3>
<p>直接丟到 queue 裡</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="no">Bar</span><span class="o">.</span><span class="n">delay</span><span class="o">.</span><span class="n">some_method</span><span class="p">(</span><span class="s2">"haha"</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>也可以以 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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</span><span class='line'><span class="n">user</span><span class="o">.</span><span class="n">delay</span><span class="o">.</span><span class="n">increase_credit</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>延遲至某短時間後再讓 worker 執行</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">user</span><span class="o">.</span><span class="n">delay_for</span><span class="p">(</span><span class="mi">1</span><span class="o">.</span><span class="n">day</span><span class="p">)</span><span class="o">.</span><span class="n">increase_credit</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>延遲至某個時間點再給 worker 執行</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">user</span><span class="o">.</span><span class="n">delay_until</span><span class="p">(</span><span class="mi">3</span><span class="o">.</span><span class="n">hour</span><span class="o">.</span><span class="n">from_now</span><span class="p">)</span><span class="o">.</span><span class="n">increase_credit</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<h3>設定 Web console</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">'slim'</span>
</span><span class='line'><span class="n">gem</span> <span class="s1">'sinatra'</span><span class="p">,</span> <span class="s1">'>= 1.3.0'</span>
</span></code></pre></td></tr></table></div></figure>
<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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">'sidekiq/web'</span>
</span><span class='line'><span class="o">.</span><span class="n">.</span><span class="o">.</span>
</span><span class='line'> <span class="n">mount</span> <span class="no">Sidekiq</span><span class="o">::</span><span class="no">Web</span> <span class="o">=></span> <span class="s1">'/sidekiq'</span>
</span></code></pre></td></tr></table></div></figure>
<p>web console 想要綁 devise 登入 (假設 scoep 為 member 且 <code>.is_admin</code> 必須為 true )<br/>
(更多可參考 <a href="https://github.com/mperham/sidekiq/wiki/Monitoring" target="_blank">https://github.com/mperham/sidekiq/wiki/Monitoring</a>)</p>
<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>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'> <span class="n">sidekiq_constraints</span> <span class="o">=</span> <span class="nb">lambda</span><span class="p">{</span> <span class="o">|</span><span class="n">request</span><span class="o">|</span>
</span><span class='line'> <span class="n">request</span><span class="o">.</span><span class="n">env</span><span class="o">[</span><span class="s1">'warden'</span><span class="o">].</span><span class="n">authenticate!</span><span class="p">({</span> <span class="ss">:scope</span> <span class="o">=></span> <span class="ss">:member</span> <span class="p">})</span> <span class="o">&&</span>
</span><span class='line'> <span class="n">request</span><span class="o">.</span><span class="n">env</span><span class="o">[</span><span class="s1">'warden'</span><span class="o">].</span><span class="n">user</span><span class="p">(</span><span class="ss">:member</span><span class="p">)</span><span class="o">.</span><span class="n">is_admin</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="n">constraints</span> <span class="n">sidekiq_constraints</span> <span class="k">do</span>
</span><span class='line'> <span class="n">mount</span> <span class="no">Sidekiq</span><span class="o">::</span><span class="no">Web</span> <span class="o">=></span> <span class="s1">'/sidekiq'</span>
</span><span class='line'> <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<h3>佈署</h3>
<figure class='code'><figcaption><span>config/deploy.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">set</span> <span class="ss">:sidekiq_cmd</span><span class="p">,</span> <span class="s2">"bundle exec sidekiq"</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:sidekiqctl_cmd</span><span class="p">,</span> <span class="s2">"bundle exec sidekiqctl"</span>
</span><span class='line'>
</span><span class='line'><span class="nb">require</span> <span class="s1">'sidekiq/capistrano'</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>config/sidekiq.yml</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='yaml'><span class='line'><span class="nn">---</span>
</span><span class='line'><span class="l-Scalar-Plain">:verbose</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">false</span>
</span><span class='line'><span class="l-Scalar-Plain">:concurrency</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">1</span>
</span><span class='line'><span class="l-Scalar-Plain">staging</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain">:concurrency</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">1</span>
</span><span class='line'><span class="l-Scalar-Plain">production</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain">:concurrency</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">10</span>
</span><span class='line'> <span class="l-Scalar-Plain">:queues</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="p-Indicator">[</span><span class="nv">default</span><span class="p-Indicator">,</span> <span class="nv">1</span><span class="p-Indicator">]</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="p-Indicator">[</span><span class="nv">mailer</span><span class="p-Indicator">,</span> <span class="nv">9</span><span class="p-Indicator">]</span>
</span></code></pre></td></tr></table></div></figure>
<h3>venus</h3>
<p>上述設定也可透過 gem <code>venus</code> 完成</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">rails</span> <span class="n">g</span> <span class="n">venus</span><span class="ss">:sidekiq</span>
</span></code></pre></td></tr></table></div></figure>
<h3>參考教學</h3>
<p><a href="http://railscasts.com/episodes/366-sidekiq" target="_blank">RailsCast</a><br/>
<a href="https://github.com/mperham/sidekiq/wiki" target="_blank">Official Document</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[讓 S3 允許 cross-domain 存取]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-06-06/aws-s3-allow-cross-origin-access/"/>
<updated>2013-06-06T01:48:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-06-06/aws-s3-allow-cross-origin-access</id>
<content type="html"><![CDATA[<p>檔案放上 <code>S3</code> 後,可能會需要透過 <code>cross-domain</code> 存取 (例如 web font)<br/>
這時可以透過 <code>S3</code> bucket 的 <code>CORS</code> 設定達成</p>
<!-- more -->
<p><img src="http://i.imgur.com/7vjeF3g.png" alt="S3 bucket CORS" /></p>
<p>開啟後如同以下內容設定即可開放 <code>GET</code> 的跨網域存取</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='xml'><span class='line'><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
</span><span class='line'><span class="nt"><CORSConfiguration</span> <span class="na">xmlns=</span><span class="s">"http://s3.amazonaws.com/doc/2006-03-01/"</span><span class="nt">></span>
</span><span class='line'> <span class="nt"><CORSRule></span>
</span><span class='line'> <span class="nt"><AllowedOrigin></span>*<span class="nt"></AllowedOrigin></span>
</span><span class='line'> <span class="nt"><AllowedMethod></span>GET<span class="nt"></AllowedMethod></span>
</span><span class='line'> <span class="nt"><AllowedHeader></span>*<span class="nt"></AllowedHeader></span>
</span><span class='line'> <span class="nt"></CORSRule></span>
</span><span class='line'><span class="nt"></CORSConfiguration></span>
</span></code></pre></td></tr></table></div></figure>
<p>如果要開放其他 HTTP method…</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>
</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
</span><span class='line'><span class="nt"><CORSConfiguration</span> <span class="na">xmlns=</span><span class="s">"http://s3.amazonaws.com/doc/2006-03-01/"</span><span class="nt">></span>
</span><span class='line'> <span class="nt"><CORSRule></span>
</span><span class='line'> <span class="nt"><AllowedOrigin></span>*<span class="nt"></AllowedOrigin></span>
</span><span class='line'> <span class="nt"><AllowedMethod></span>GET<span class="nt"></AllowedMethod></span>
</span><span class='line'> <span class="nt"><AllowedMethod></span>POST<span class="nt"></AllowedMethod></span>
</span><span class='line'> <span class="nt"><AllowedMethod></span>PUT<span class="nt"></AllowedMethod></span>
</span><span class='line'> <span class="nt"><AllowedHeader></span>*<span class="nt"></AllowedHeader></span>
</span><span class='line'> <span class="nt"></CORSRule></span>
</span><span class='line'><span class="nt"></CORSConfiguration></span>
</span></code></pre></td></tr></table></div></figure>
<h3>參考資料</h3>
<p><a href="http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html" target="_blank">http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[安裝與設定 unicorn 實現佈署時 zero down time]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-06-03/unicorn-rails-and-capistrano/"/>
<updated>2013-06-03T11:27:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-06-03/unicorn-rails-and-capistrano</id>
<content type="html"><![CDATA[<p>本文章的 code 可參考公開的 pull request<br/>
<a href="https://github.com/5fpro/cupid/pull/11/files" target="_blank">https://github.com/5fpro/cupid/pull/11/files</a><br/>
這是基礎到不行的設定方式,考量到 server 效能在設定上的 best practice 將會在日後持續 update 本文。</p>
<!-- more -->
<h3>安裝 gem</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>
<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">:development</span> <span class="k">do</span>
</span><span class='line'> <span class="n">gem</span> <span class="s1">'capistrano-unicorn'</span><span class="p">,</span> <span class="ss">:require</span> <span class="o">=></span> <span class="kp">false</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">'unicorn'</span>
</span></code></pre></td></tr></table></div></figure>
<p>本文所採用的 gem 版本</p>
<figure class='code'><figcaption><span>Gemfile.lock</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">capistrano</span><span class="o">-</span><span class="n">unicorn</span> <span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">1</span><span class="o">.</span><span class="mi">9</span><span class="p">)</span>
</span><span class='line'><span class="n">unicorn</span> <span class="p">(</span><span class="mi">4</span><span class="o">.</span><span class="mi">6</span><span class="o">.</span><span class="mi">2</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<h3>佈署設定</h3>
<p>這裡的 <code>production.rb</code> 是針對 <code>rails_env=production</code>,而非 capistrano 中 multistage 的 production</p>
<figure class='code'><figcaption><span>config/unicorn/production.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="n">worker_processes</span> <span class="mi">1</span>
</span><span class='line'><span class="n">preload_app</span> <span class="kp">true</span>
</span><span class='line'>
</span><span class='line'><span class="n">listen</span> <span class="s1">'/tmp/unicorn.cupid.sock'</span> <span class="c1"># sock 檔名可依照 app 需求設定</span>
</span><span class='line'>
</span><span class='line'><span class="n">stderr_path</span> <span class="s1">'log/unicorn.error.log'</span>
</span><span class='line'><span class="n">stdout_path</span> <span class="s1">'log/unicorn.log'</span>
</span><span class='line'>
</span><span class='line'><span class="n">pid</span> <span class="s2">"tmp/pids/unicorn.pid"</span>
</span><span class='line'>
</span><span class='line'><span class="n">rails_env</span> <span class="o">=</span> <span class="no">ENV</span><span class="o">[</span><span class="s1">'RAILS_ENV'</span><span class="o">]</span> <span class="o">||</span> <span class="s1">'production'</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># before/after fork 可自行擴充</span>
</span><span class='line'>
</span><span class='line'><span class="n">before_fork</span> <span class="k">do</span> <span class="o">|</span><span class="n">server</span><span class="p">,</span> <span class="n">worker</span><span class="o">|</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">after_fork</span> <span class="k">do</span> <span class="o">|</span><span class="n">server</span><span class="p">,</span> <span class="n">worker</span><span class="o">|</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>(也可以把上述檔案放在 <code>config/unicorn.rb</code>)</p>
<h3>server 上的 nginx.conf</h3>
<figure class='code'><figcaption><span>nginx.conf</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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">upstream</span> <span class="n">my_app</span> <span class="p">{</span> <span class="c1"># upstream 名稱可自定</span>
</span><span class='line'> <span class="n">server</span> <span class="n">unix</span><span class="ss">:/</span><span class="n">tmp</span><span class="o">/</span><span class="n">unicorn</span><span class="o">.</span><span class="n">cupid</span><span class="o">.</span><span class="n">sock</span><span class="p">;</span> <span class="c1"># 這裡要和 config/unicorn/production.rb 中 listen 的設定對應</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="n">server</span> <span class="p">{</span>
</span><span class='line'> <span class="n">listen</span> <span class="mi">80</span><span class="p">;</span>
</span><span class='line'> <span class="n">server_name</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="c1"># passenger_enabled on; # 原本要設定 passenger 的記得要拿掉</span>
</span><span class='line'> <span class="c1"># .......</span>
</span><span class='line'>
</span><span class='line'> <span class="n">location</span> <span class="o">/</span> <span class="p">{</span>
</span><span class='line'> <span class="n">proxy_set_header</span> <span class="n">X</span><span class="o">-</span><span class="no">Real</span><span class="o">-</span><span class="no">IP</span> <span class="vg">$remote_addr</span><span class="p">;</span>
</span><span class='line'> <span class="n">proxy_set_header</span> <span class="n">X</span><span class="o">-</span><span class="no">Forwarded</span><span class="o">-</span><span class="no">For</span> <span class="vg">$proxy_add_x_forwarded_for</span><span class="p">;</span>
</span><span class='line'> <span class="n">proxy_set_header</span> <span class="no">Host</span> <span class="vg">$http_host</span><span class="p">;</span>
</span><span class='line'> <span class="n">proxy_pass</span> <span class="n">http</span><span class="ss">:/</span><span class="o">/</span><span class="n">my_app</span><span class="p">;</span> <span class="c1"># upstream 名稱</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="n">location</span> <span class="o">~</span> <span class="o">^/</span><span class="p">(</span><span class="n">assets</span><span class="p">)</span><span class="o">/</span> <span class="p">{</span> <span class="c1"># 這裡是 precompile 後的 assets file 路徑</span>
</span><span class='line'> <span class="n">gzip_static</span> <span class="n">on</span><span class="p">;</span> <span class="c1"># to serve pre-gzipped version</span>
</span><span class='line'> <span class="n">expires</span> <span class="n">max</span><span class="p">;</span>
</span><span class='line'> <span class="n">add_header</span> <span class="no">Cache</span><span class="o">-</span><span class="no">Control</span> <span class="kp">public</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="c1"># .......</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<h3>把 unicorn 重啟的 hook 掛到 deploy.rb 中</h3>
<figure class='code'><figcaption><span>config/deploy.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">'capistrano-unicorn'</span>
</span><span class='line'><span class="n">after</span> <span class="s1">'deploy:restart'</span><span class="p">,</span> <span class="s1">'unicorn:restart'</span>
</span></code></pre></td></tr></table></div></figure>
<p>done!</p>
<h3>如何在本機測試 unicorn</h3>
<p><code>bundle exec unicorn</code></p>
<p>Go to http://localhost:8080</p>
<h3>參考資料</h3>
<ul>
<li>更多 unicorn 可以在 cap 指令中的應用: <a href="https://github.com/sosedoff/capistrano-unicorn/blob/master/lib/capistrano-unicorn/capistrano_integration.rb" target="_blank">https://github.com/sosedoff/capistrano-unicorn/blob/master/lib/capistrano-unicorn/capistrano_integration.rb</a></li>
<li>unicorn 設定檔說明: <a href="https://raw.github.com/defunkt/unicorn/master/examples/unicorn.conf.rb" target="_blank">https://raw.github.com/defunkt/unicorn/master/examples/unicorn.conf.rb</a></li>
<li>Github Blog 上說明他們自己的 unicorn 如何設定: <a href="https://github.com/blog/517-unicorn" target="_blank">https://github.com/blog/517-unicorn</a></li>
<li>其他 unicorn 設定相關教學:
<ul>
<li><a href="http://tech.gadii.net/blog/2013/03/07/rails-deploy-ji-chu-jiao-xue/" target="_blank">http://tech.gadii.net/blog/2013/03/07/rails-deploy-ji-chu-jiao-xue/</a></li>
<li><a href="https://devcenter.heroku.com/articles/rails-unicorn" target="_blank">https://devcenter.heroku.com/articles/rails-unicorn</a></li>
<li><a href="http://ruby-china.org/topics/471" target="_blank">http://ruby-china.org/topics/471</a></li>
</ul>
</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[利用 Swagger 產生互動式 API 文件]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-05-04/swagger-api-doc-rails/"/>
<updated>2013-05-04T20:48:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-05-04/swagger-api-doc-rails</id>
<content type="html"><![CDATA[<p><a href="https://developers.helloreverb.com/swagger/" target="_blank">Swagger</a> 是一套由 HTML + Javascript 撰寫的 REST API 文件的框架。 (core 是以 scala 寫的)</p>
<!-- more -->
<p>從 <a href="http://petstore.swagger.wordnik.com/" target="_blank">Demo 頁</a> 可了解到 Swagger 不僅僅提供 API 的規格資訊,也提供互動介面讓開發者可以直接輸入參數進行測試。<br/>
<img src="http://i.imgur.com/a5vAGKz.png" /></p>
<p>亦支援 GET & POST 以外的 http method (PUT、DELETE)。</p>
<p><img src="http://i.imgur.com/L3c5TTt.png" /></p>
<p>Demo 頁面的 source code 在<a href="https://github.com/wordnik/swagger-ui" target="_blank"> Github </a>上。也可以參考 wordnik 的<a href="http://developer.wordnik.com/docs.html" target="_blank"> 官方正式 API 文件 </a>。</p>
<p>API 文件內容完全是透過 ajax 取得 JSON data 產生的,因此必須提供 server 吐出符合 Swagger 文件中所定義的 JSON 格式,讓前端網頁能夠生成 API 文件的介面。</p>
<p><img src="http://i.imgur.com/iC3LFIL.png" border="1" style="border-color:#000000" /></p>
<p>在 Swagger 文件中所定義的物件有:</p>
<ol>
<li><code>doc</code>: 代表整份 API 文件 (<a href="https://github.com/wordnik/swagger-core/wiki/Resource-Listing" target="_blank">規格文件</a>)</li>
<li><code>resource</code>: API 文件下的分類目錄 (<a href="https://github.com/wordnik/swagger-core/wiki/API-Declaration" target="_blank">規格文件</a>)</li>
<li><code>api</code>: 每一條 REST Request (<a href="https://github.com/wordnik/swagger-core/wiki/API-Declaration" target="_blank">規格文件</a>)</li>
<li><code>parameter</code>: <code>api</code> 下的每個參數 (<a href="https://github.com/wordnik/swagger-core/wiki/Parameters" target="_blank">規格文件</a>)</li>
<li><code>model</code>: 自訂的 return data type (<a href="https://github.com/wordnik/swagger-core/wiki/Datatypes" target="_blank">規格文件</a>)</li>
</ol>
<p>鑿於定義相當繁多且複雜,Swagger 本身有提供<a href="https://github.com/wordnik/swagger-codegen/tree/master/samples/server-generator" target="_blank">部分語言的 API 文件生成後台</a> (Ruby 開發者可選擇 sinatra),讓開發者能夠花最少的時間開始使用 Swagger。</p>
<p>但筆者仍覺得 Swagger 使開發者進入狀況的門檻仍高,因此花了點時間以 rails app 開發 Swagger json data 的管理後台生成 swagger API 文件,提供後台的 web 操作介面來產生 Swagger 的 API 文件。</p>
<p>Github: <a href="https://github.com/marsz/swagger-rails" target="_blank">https://github.com/marsz/swagger-rails</a><br/>
Demo: <a href="http://swagger.5fpro.com/" target="_blank">http://swagger.5fpro.com/</a></p>
<p>功能特色:</p>
<ol>
<li>FB 登入/註冊,單一帳號下可建立多筆 <code>doc</code></li>
<li>自訂 API 實際測試的目標網域</li>
<li>可設定獨立網域 (FQDN),若沒有設定系統也會自動產生一組給你用</li>
<li><code>resource</code> 可排序</li>
</ol>
<p>讓我們 step by step 來建立 API 文件吧。<br/>
範例是小弟在早期自己寫的 API,用來提供台灣縣市鄉鎮的資料庫。</p>
<ol>
<li>建立 <code>doc</code>,內容如下:<br/>
<img src="http://i.imgur.com/dM1Ori8.png" /></li>
<li>建立 <code>doc</code> 後,系統會提供你 API 實測時的網址格式<br/>
<img src="http://i.imgur.com/RNsHmMx.png" /></li>
<li>建立 <code>resource</code> (圖略), <code>resource</code> 可以用來當做是管理許多 API 的目錄</li>
<li>建立 <code>api</code>: 選擇 http method 和 path<br/>
<img src="http://i.imgur.com/x9wfS0U.png" /><br/>
若 API 參數在 path 中,可用大括號包起來,必且給予參數名稱</li>
<li>填寫 return data type,若為某個 model 的 array 可以以圖內的格式表示<br/>
<img src="http://i.imgur.com/5TyRs6L.png" /></li>
<li>api path 內有參數的話,底下的 parameters 也必須增加 <code>parameter type</code> 為 <code>path</code> 的參數 (如圖),名稱和大括號內對應<br/>
<img src="http://i.imgur.com/98IsmNe.png" /></li>
<li>有關 <code>model</code> 的定義,可在 doc 頁找到,這裡的定義與否不會影響文件的正常顯示,有定義的話文件也會顯示出來,內容也就更完整囉<br/>
<img src="http://i.imgur.com/F1vZR2E.png" /></li>
<li>點擊 doc information 內的連結即可看到結果(<a href="http://gaia-doc.5fpro.tw/#!/3/api_6_get_2" target="_blank">http://gaia-doc.5fpro.tw/#!/3/api_6_get_2</a>)<br/>
<img src="http://i.imgur.com/8x0rLQX.png" /></li>
<li>當然,API 實測要有資料,必須實作 <a href="http://gaia.5fpro.tw/cities/1.json" target="_blank">http://gaia.5fpro.tw/cities/1.json</a> 回傳的 JSON data 才行。</li>
</ol>
<p>目前的 swagger-rails 仍有許多待增加的功能:</p>
<ol>
<li>多人協作</li>
<li>修改記錄</li>
<li>自訂前端 CSS</li>
<li>後台介面優化</li>
<li>100% 實作 Swagger 所有支援的格式</li>
</ol>
<p>最後附上筆者目前正式對外開放的 API 文件給各位參考:</p>
<ol>
<li><a href="http://api-doc.thewall.tw/" target="_blank">THEWALL 這牆音樂</a></li>
<li><a href="http://gaia-doc.5fpro.tw/" target="_blank">台灣縣市鄉鎮資料庫</a>, 含郵遞區號</li>
<li><a href="http://medusa-doc.5fpro.com/" target="_blank">爬蟲系統</a> (暫不開放申請)</li>
</ol>
<p>筆者目前透過自己蓋的 <code>swagger-rails</code> 用於內部溝通居多,不論在 mobile app 開發或跨語言的資料傳遞,透過 Swagger 介面的 API 實測功能,使用者很快就可以了解每條 API 的取用方式與資料格式,大大減少了溝通的成本。</p>
<p>Swagger 參考資料:</p>
<ol>
<li><a href="https://github.com/wordnik/swagger-core/wiki" target="_blank">Swagger Specification</a></li>
<li><a href="https://github.com/wordnik/swagger-core/wiki/Downloads" target="_blank">Swagger Downloads</a></li>
<li><a href="https://developers.helloreverb.com/swagger/" target="_blank">Official Site</a></li>
</ol>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[server 端允許 ajax cross domain 存取]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-04-28/server-side-accept-cross-domain-ajax-request/"/>
<updated>2013-04-28T13:07:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-04-28/server-side-accept-cross-domain-ajax-request</id>
<content type="html"><![CDATA[<p>在 controller 中加入以下即可允許來自 cross domain 的 ajax request</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">response</span><span class="o">.</span><span class="n">headers</span><span class="o">[</span><span class="s2">"Access-Control-Allow-Origin"</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"*"</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Redis 在 Passenger 重起後出現 'reconnect to Redis after forking' 的錯誤訊息]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-04-13/redis-reconnect-after-fork/"/>
<updated>2013-04-13T22:02:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-04-13/redis-reconnect-after-fork</id>
<content type="html"><![CDATA[<p>自 <code>redis</code> 升級,每次透過 <code>capistrano</code> 佈署後,連線 server 都會噴出 “Tried to use a connection from a child process without reconnecting. You need to reconnect to Redis after forking.” 的錯誤訊息。</p>
<!-- more -->
<p>原因在於 <code>redis</code> 的 <a href="https://github.com/redis/redis-rb" target="_blank">client gem</a>。</p>
<p>因此必須在每次 passenger restart 後,也讓 redis client 進行重啓。可參考以下,必須於 initializer 或 application.rb 中執行。</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='ruby'><span class='line'><span class="k">if</span> <span class="n">defined?</span><span class="p">(</span><span class="no">PhusionPassenger</span><span class="p">)</span>
</span><span class='line'> <span class="no">PhusionPassenger</span><span class="o">.</span><span class="n">on_event</span><span class="p">(</span><span class="ss">:starting_worker_process</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">forked</span><span class="o">|</span>
</span><span class='line'> <span class="k">if</span> <span class="n">forked</span>
</span><span class='line'> <span class="no">Redis</span><span class="o">.</span><span class="n">current</span> <span class="o">=</span> <span class="no">Redis</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:host</span> <span class="o">=></span> <span class="s2">"127.0.0.1"</span><span class="p">,</span> <span class="ss">:port</span> <span class="o">=></span> <span class="mi">6379</span><span class="p">)</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>除了 <code>redis</code> 之外,其他透過 redis 應用的 gem 也都會有類似的問題,例如 <code>resque</code>、<code>redis-store</code>、<code>redis-object</code>、<code>sidekiq</code> 等。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[新版的 git (1.7 以上) 在 merge 時預設不開編輯器的設定]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-04-09/git-merge-no-edit-default/"/>
<updated>2013-04-09T02:02:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-04-09/git-merge-no-edit-default</id>
<content type="html"><![CDATA[<p>打開你的 shell rc 例如 <code>~/.zshrc</code> 或 <code>~/bashrc</code><br/>
插入以下</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>export GIT_MERGE_AUTOEDIT=no</span></code></pre></td></tr></table></div></figure>
<!-- more -->
<p>之後 merge –no-ff 的指令就都會預設用 auto message 做 commit 啦<br/>
如果想要強制編輯時,可以用 –edit 參數</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>git merge branch_name --no-ff --edit</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[修正 IE 無法透過 cross-domain AJAX 取得 JSON 物件]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-03-29/ie-jquery-ajax-jsonp-n-cross-domain-n-cache-control-public/"/>
<updated>2013-03-29T22:52:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-03-29/ie-jquery-ajax-jsonp-n-cross-domain-n-cache-control-public</id>
<content type="html"><![CDATA[<p>controller 中的 <code>respond_to</code> 可用來 return 指定的 format 供 JS 取用 API 資料<br/>
但很不幸的 IE 9 以下在透過 jquery 中的 getJSON 無法取得 return 的 json 物件。</p>
<!-- more -->
<p>server 端的 action</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">index</span>
</span><span class='line'> <span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="o">[</span><span class="s2">"Access-Control-Allow-Origin"</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"*"</span>
</span><span class='line'> <span class="n">expires_in</span> <span class="mi">1</span><span class="o">.</span><span class="n">day</span><span class="p">,</span> <span class="ss">:public</span> <span class="o">=></span> <span class="kp">true</span>
</span><span class='line'> <span class="vi">@data</span> <span class="o">=</span> <span class="no">SomeModel</span><span class="o">.</span><span class="n">all</span>
</span><span class='line'> <span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span>
</span><span class='line'> <span class="n">f</span><span class="o">.</span><span class="n">json</span><span class="p">{</span> <span class="n">render</span> <span class="ss">:json</span> <span class="o">=></span> <span class="vi">@data</span> <span class="p">}</span>
</span><span class='line'> <span class="n">f</span><span class="o">.</span><span class="n">xml</span><span class="p">{</span> <span class="n">render</span> <span class="ss">:xml</span> <span class="o">=></span> <span class="vi">@data</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>client 端的 javascript</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="nx">getJSON</span><span class="p">(</span><span class="s2">"http://apihost.com/products.json"</span><span class="p">,</span><span class="s2">"jsonp"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">products</span><span class="p">){</span>
</span><span class='line'> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">products</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>結果: IE9 以下不 work,其他瀏覽器沒問題(生氣)</p>
<p>解決此問題的方法必須例用 jquery jsonp callback 的方式達到目的即可<br/>
因此 server 端的 response 的 content-type 必須是 javascript (見 <a href="http://d.pr/i/66d0" target="_blank">此圖</a>)</p>
<p>server 端寫法</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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">index</span>
</span><span class='line'> <span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="o">[</span><span class="s2">"Access-Control-Allow-Origin"</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"*"</span>
</span><span class='line'> <span class="n">expires_in</span> <span class="mi">1</span><span class="o">.</span><span class="n">day</span><span class="p">,</span> <span class="ss">:public</span> <span class="o">=></span> <span class="kp">true</span>
</span><span class='line'> <span class="vi">@data</span> <span class="o">=</span> <span class="no">SomeModel</span><span class="o">.</span><span class="n">all</span>
</span><span class='line'> <span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span>
</span><span class='line'> <span class="n">f</span><span class="o">.</span><span class="n">json</span><span class="p">{</span> <span class="n">render</span> <span class="ss">:json</span> <span class="o">=></span> <span class="vi">@data</span> <span class="p">}</span>
</span><span class='line'> <span class="n">f</span><span class="o">.</span><span class="n">xml</span><span class="p">{</span> <span class="n">render</span> <span class="ss">:xml</span> <span class="o">=></span> <span class="vi">@data</span> <span class="p">}</span>
</span><span class='line'> <span class="n">f</span><span class="o">.</span><span class="n">js</span><span class="p">{</span> <span class="ss">:json</span> <span class="o">=></span> <span class="vi">@data</span><span class="p">,</span> <span class="ss">:callback</span> <span class="o">=></span> <span class="n">params</span><span class="o">[</span><span class="ss">:callback</span><span class="o">]</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>client 端的 javascript</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="nx">getJSON</span><span class="p">(</span><span class="s2">"http://apihost.com/products.js?callback=?"</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">){</span>
</span><span class='line'> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>搞定!!!</p>
<p>server 端其他寫法的補充:</p>
<p>開啟 cross-domain 的 ajax request</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">response</span><span class="o">.</span><span class="n">headers</span><span class="o">[</span><span class="s2">"Access-Control-Allow-Origin"</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"*"</span>
</span></code></pre></td></tr></table></div></figure>
<p>開啟 cache-control 為 public:</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">expires_in</span> <span class="mi">1</span><span class="o">.</span><span class="n">day</span><span class="p">,</span> <span class="ss">:public</span> <span class="o">=></span> <span class="kp">true</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[我寫的 gem - venus 簡介]]></title>
<link href="http://rubyist.marsz.tw/blog/2013-03-13/rubygems-venus/"/>
<updated>2013-03-13T13:12:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2013-03-13/rubygems-venus</id>
<content type="html"><![CDATA[<p>因受到了<a href="http://railsapps.github.com/rails-composer/" target="_blank"> rails composor </a> 的影響,決定也來寫一個客製化的 rails generator。<br/>
但後來又覺得只能在開新專案用的話,使用頻率也不太高…</p>
<!-- more -->
<p>鑿於在許多專案中,總是為了要安裝某些 gem 而必須再回去翻寫過專案中的 code 或上官網找範例 code 做 copy/paste + 修改,於是我決定寫一個 generator 來設定這些常用的 gem,僅需要如同 rails composor 一樣回答一些問題就可以把所有的設定弄到好。</p>
<p>因此 venus 因應而生</p>
<p>安裝: <a href="https://rubygems.org/gems/venus" target="_blank">https://rubygems.org/gems/venus</a> <br/>
源碼: <a href="https://github.com/marsz/venus" target="_blank">https://github.com/marsz/venus</a></p>
<p>以下逐一介紹各個指令</p>
<p><code>rails generate venus:init</code></p>
<p>專案初始化設定,例如移除 public/index.html,安裝必要的 gem 例如分頁用的 <code>kminari</code>,剛 new 好的 rails 專案適合執行此指令。</p>
<p><code>rails generate venus:mysql</code></p>
<p>設定 mysql,包含從 <code>Gemfile</code> 安裝 mysql2,設定 <code>database.yml</code> 以及 <code>database.yml.example</code>,最後再將 <code>config/database.yml</code> 加到 .gitignore 中。</p>
<p><code>rails generate venus:paginate</code></p>
<p>單獨安裝分頁用的 gem - <code>kminari</code>,也會問你要不要產生客製化的 view 出來。</p>
<p><code>rails generate venus:simple_form</code></p>
<p>view 使用 form 必備的 <a href="https://github.com/plataformatec/simple_form" target="_blank">simple_form</a>,預設會產生 bootstrap wrapper 的設定檔。也會詢問是否要順便安裝 <a href="https://github.com/ryanb/nested_form" target="_blank">nested_form</a>,安裝 nested_form 需要在 js 中 require gem 裡面包好的 JS,所以也會詢問 require code 和 example code 要放的檔案路徑。</p>
<p><code>rails generate venus:settingslogic</code></p>
<p>gem - <a href="https://github.com/binarylogic/settingslogic" target="_blank"><code>settingslogic</code></a>。可以將多個 yml 的設定檔放在此 gem 所讀取的 yaml 下,使其能夠容易管理。此 generator 同時也會產生 .example 檔以及加入 .yml 到 .gitignore 下。</p>
<p><code>rails generate venus:rspec</code></p>
<p>安裝並且設定 <code>rspec</code>,並且移除 test 目錄,在 <code>config/application.rb</code> 中設定 generate controller 時,不自動產生 assets files 和 helper。</p>
<p><code>rails generate venus:devise</code></p>
<p>安裝並且設定 scope 為 user 的 devise gem。</p>
<p><code>rails generate venus:omniauth</code></p>
<p>會先檢查是否有安裝 settingslogic 以及 devise,然後再安裝 omniauth,過程中會詢問 facebook / twitter / github 登入的安裝與否。</p>
<p><code>rails generate venus:redis</code></p>
<p>安裝並且設定 redis client gem <a href="https://github.com/redis/redis-rb" target="_blank">redis-rb</a> 。</p>
<p><code>rails generate venus:aws</code></p>
<p>安裝並且設定 Amazon <a href="https://github.com/aws/aws-sdk-ruby" target="_blank">官方的 ruby client </a>。過程中會先檢查 settingslogic,並且將 api key 和 secret 存到其中。最後也會詢問否需要順便安裝 Amazon Simple Email Service (SES),用來發 email。</p>
<p><code>rails generate venus:carrierwave</code></p>
<p>安裝並且設定 carrierwave,其中包含 rmagick 進行縮圖,以及 fog 將檔案上傳至S3。過程中會安裝 aws-sdk,所以也會順便詢問 SES 的設定 :p。最後會產生一個 <code>venus_uploader.rb</code> 做為範例。</p>
<p><code>rails generate venus:jqueryui</code></p>
<p>安裝 jquery ui 的 gem。其中會詢問是否要安裝 datepicker,包含產生 trigger 用的 js 範例 code。gem 的 參考連結 => <a href="https://github.com/joliss/jquery-ui-rails" target="_blank">https://github.com/joliss/jquery-ui-rails</a>。 (若有要安裝 datepicker 的話,也會詢問語系)</p>
<p><code>rails generate venus:chosen</code></p>
<p>安裝 <a href="https://github.com/tsechingho/chosen-rails" target="_blank">chosen-rails</a> 並且提供 trigger chosen 的範例 js code。</p>
<p><code>rails generate venus:bootstrap</code></p>
<p>安裝 <code>twitter bootstrap</code> ,包含 gem 設定、 assets require,最後產生範例 layout 檔於 <code>app/views/layouts/</code> 下。內建提供 <a href="http://wrapbootstrap.com/preview/WB0F35928" target="_blank">unicorn admin</a> 的版型套用,蓋後台超爽 XD</p>
<h1>TODOs</h1>
<p>對於此 gem 未來將會逐漸加入我自己寫的 best practice :p 也望各位大大能不吝指教或回報 bug :D</p>
<ul>
<li>sidekiq : 強大的 background job gem</li>
<li>unicorn : 配合 capistrano 讓佈署時可以 zero down time</li>
<li><a href="https://github.com/airblade/paper_trail" target="_blank">paper_trail</a> : 對 model 進行版本控制的 gem</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[自動化產生 ER 圖的 rubygem]]></title>
<link href="http://rubyist.marsz.tw/blog/2012-11-13/auto-generate-erd-graph/"/>
<updated>2012-11-13T05:39:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2012-11-13/auto-generate-erd-graph</id>
<content type="html"><![CDATA[<p>參考連結:<br/>
1. 官網 : <a href="http://rails-erd.rubyforge.org/" target="_blank">http://rails-erd.rubyforge.org/</a><br/>
2. 相關教學 : <a href="http://zool.me/rails/2010/12/29/Rails-generate-entity-relationship-diagram-projects/" target="_blank">http://zool.me/rails/2010/12/29/Rails-generate-entity-relationship-diagram-projects/</a></p>
<!-- more -->
<h3>系統需求</h3>
<p>MAC OS 請先安裝 <code>brew</code></p>
<h3>安裝 Graphviz</h3>
<h5>MAC OS</h5>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>brew install cairo pango graphviz</span></code></pre></td></tr></table></div></figure>
<p>若無法順利安裝可至 <a href="http://www.graphviz.org/Download_macos.php" target="_blank">graphviz for MAC OS download</a> 頁面下載對應的系統,直接打開 finder 以 window 介面安裝</p>
<h5>Ubuntu</h5>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo aptitude install graphviz</span></code></pre></td></tr></table></div></figure>
<h3>Rails 設定</h3>
<h5>Gemfile</h5>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">group</span> <span class="ss">:development</span> <span class="k">do</span>
</span><span class='line'> <span class="n">gem</span> <span class="s2">"rails-erd"</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<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">bundle</span> <span class="n">install</span>
</span></code></pre></td></tr></table></div></figure>
<h3>生成 ERD</h3>
<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">bundle</span> <span class="nb">exec</span> <span class="n">rake</span> <span class="n">erd</span>
</span></code></pre></td></tr></table></div></figure>
<p>生成的 ERD 會在專案目錄下的 erd.pdf</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Rubygems 處理 Amazon Web Service (AWS) EC2]]></title>
<link href="http://rubyist.marsz.tw/blog/2012-11-09/rubygeems-for-aws-ec2/"/>
<updated>2012-11-09T13:55:00+08:00</updated>
<id>http://rubyist.marsz.tw/blog/2012-11-09/rubygeems-for-aws-ec2</id>
<content type="html"><![CDATA[<p>參考: <a href="https://github.com/grempe/amazon-ec2" target="_blank">https://github.com/grempe/amazon-ec2</a></p>
<!-- more -->
<h3>安裝設定</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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="s1">'amazon-ec2'</span><span class="p">,</span> <span class="ss">:require</span> <span class="o">=></span> <span class="s2">"AWS"</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>config/aws.yml</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='yaml'><span class='line'><span class="l-Scalar-Plain">development</span><span class="p-Indicator">:</span> <span class="nl">&default</span>
</span><span class='line'> <span class="l-Scalar-Plain">:access_key_id</span><span class="p-Indicator">:</span> <span class="s">"abcdabcd"</span>
</span><span class='line'> <span class="l-Scalar-Plain">:secret_access_key</span><span class="p-Indicator">:</span> <span class="s">"abcdabcd"</span>
</span><span class='line'> <span class="l-Scalar-Plain">:host</span><span class="p-Indicator">:</span> <span class="s">"ap-southeast-1.ec2.amazonaws.com"</span>
</span><span class='line'><span class="l-Scalar-Plain">test</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain"><<</span><span class="p-Indicator">:</span> <span class="nv">*default</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>access_key_id</code> 和 <code>secret_access_key</code> 可至 <a href="https://portal.aws.amazon.com/gp/aws/developer/account/index.html?action=access-key" target="_blank">AWS Security Credentials</a> 查看<br/>
<code>host</code> 則是目標 region 所對應的 endpoint,對應表可至 <a href="https://github.com/garnaat/missingcloud/blob/master/aws.json#L372" target="_blank">https://github.com/garnaat/missingcloud/blob/master/aws.json#L372</a> 查看</p>
<p>養成好習慣, 請勿將 yaml 檔 commit 進去…</p>
<figure class='code'><figcaption><span>.gitignore</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">config</span><span class="o">/</span><span class="n">aws</span><span class="o">.</span><span class="n">yml</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>config/aws.yml.example</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='yaml'><span class='line'><span class="c1"># to see region and host mapping :</span>
</span><span class='line'><span class="c1"># https://github.com/garnaat/missingcloud/blob/master/aws.json#L372</span>
</span><span class='line'><span class="l-Scalar-Plain">development</span><span class="p-Indicator">:</span> <span class="nl">&default</span>
</span><span class='line'> <span class="l-Scalar-Plain">:access_key_id</span><span class="p-Indicator">:</span> <span class="s">""</span>
</span><span class='line'> <span class="l-Scalar-Plain">:secret_access_key</span><span class="p-Indicator">:</span> <span class="s">""</span>
</span><span class='line'> <span class="l-Scalar-Plain">:host</span><span class="p-Indicator">:</span> <span class="s">""</span>
</span><span class='line'><span class="l-Scalar-Plain">test</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain"><<</span><span class="p-Indicator">:</span> <span class="nv">*default</span>
</span></code></pre></td></tr></table></div></figure>
<h3>使用方法</h3>
<ul>
<li>初始化</li>
</ul>
<figure class='code'><figcaption><span>example.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">config</span> <span class="o">=</span> <span class="no">YAML</span><span class="o">::</span><span class="nb">load</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">"</span><span class="si">#{</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="si">}</span><span class="s2">/config/aws.yml"</span><span class="p">))</span><span class="o">[</span><span class="no">Rails</span><span class="o">.</span><span class="n">env</span><span class="o">]</span>
</span><span class='line'><span class="n">ec2</span> <span class="o">=</span> <span class="no">AWS</span><span class="o">::</span><span class="no">EC2</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:access_key_id</span> <span class="o">=></span> <span class="n">config</span><span class="o">[</span><span class="ss">:access_key_id</span><span class="o">]</span><span class="p">,</span> <span class="ss">:secret_access_key</span> <span class="o">=></span> <span class="n">config</span><span class="o">[</span><span class="ss">:secret_access_key</span><span class="o">]</span><span class="p">,</span> <span class="ss">:server</span> <span class="o">=></span> <span class="n">config</span><span class="o">[</span><span class="ss">:host</span><span class="o">]</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<ul>
<li>取得 instance 列表</li>
</ul>
<figure class='code'><figcaption><span>exmaple.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">instances</span> <span class="o">=</span> <span class="n">ec2</span><span class="o">.</span><span class="n">describe_instances</span>
</span><span class='line'><span class="c1"># instances["reservationSet"]["item"] 才會取得 array</span>
</span></code></pre></td></tr></table></div></figure>
<ul>
<li>取得所有 snapshots (自己 create 的)</li>
</ul>