<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[慕凡(@ryudoawaru)'s blog]]></title>
  <link href="http://ryudo.tw/atom.xml" rel="self"/>
  <link href="http://ryudo.tw/"/>
  <updated>2017-02-03T17:37:33+08:00</updated>
  <id>http://ryudo.tw/</id>
  <author>
    <name><![CDATA[Mu-Fan Teng]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Install Ruby / Rails / Passenger / PostgreSQL Stack in RHEL and variant OS (後篇)]]></title>
    <link href="http://ryudo.tw/blog/2017/02/02/install-ruby-rails-passenger-postgresql-into-rhel-2017-02/"/>
    <updated>2017-02-02T17:32:00+08:00</updated>
    <id>http://ryudo.tw/blog/2017/02/02/install-ruby-rails-passenger-postgresql-into-rhel-2017-02</id>
    <content type="html"><![CDATA[<p>接續<a href="http://ryudo.tw/blog/2017/01/24/install-ruby-rails-passenger-postgresql-into-rhel-2017/">前篇</a>，本篇內容包含：</p>

<ul>
<li>Nginx 設定檔</li>
<li>設定 systemd 啟動檔</li>
<li>Logrotate &amp; Iptables 設定</li>
</ul>


<h3>Nginx 設定檔</h3>

<p>由於編譯 Nginx 時把 prefix 設定在 <code>/usr/local/nginx</code> 下，所以設定檔就在 <code>/usr/local/nginx/conf</code>  下，先編輯 <code>/usr/local/nginx/conf/nginx.conf</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>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
</pre></td><td class='code'><pre><code class='nginx'><span class='line'><span class="k">user</span>  <span class="s">nobody</span><span class="p">;</span> <span class="c1">#這邊的 user 和 Rails App 的 user 是不一樣的設定，但是要考慮到 Asset File 的存取，也就是這個 user 必需要可以唯讀 Rails App 的 public 目錄</span>
</span><span class='line'><span class="k">worker_processes</span>  <span class="mi">4</span><span class="p">;</span>
</span><span class='line'><span class="k">error_log</span>  <span class="s">logs/error.log</span>  <span class="s">info</span><span class="p">;</span>
</span><span class='line'><span class="k">pid</span>       <span class="s">/var/run/nginx.pid</span><span class="p">;</span> <span class="c1">#設定 pid file 的位置，必需和後面 systemd 設定檔一致</span>
</span><span class='line'><span class="k">worker_rlimit_nofile</span> <span class="mi">40960</span><span class="p">;</span>
</span><span class='line'><span class="k">events</span> <span class="p">{</span>
</span><span class='line'>    <span class="kn">worker_connections</span>  <span class="mi">10240</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span><span class="c1">#worker_rlimit_nofile 和 worker_connections：為了突破系統開啟檔案上限的設定，必需一起設定，一般來說 worker_rlimit_nofile 為 worker_connections x worker_processes</span>
</span><span class='line'>
</span><span class='line'><span class="k">http</span> <span class="p">{</span>
</span><span class='line'>  <span class="kn">include</span>       <span class="s">mime.types</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">default_type</span>  <span class="s">application/octet-stream</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">access_log</span> <span class="s">logs/access.log</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">sendfile</span>        <span class="no">on</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">keepalive_timeout</span>  <span class="mi">65</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">gzip</span>  <span class="no">on</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">send_timeout</span> <span class="mi">600</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">gzip_min_length</span>  <span class="mi">1000</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">gzip_buffers</span>     <span class="mi">4</span> <span class="mi">8k</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">gzip_types</span>       <span class="s">text/plain</span> <span class="s">application/x-javascript</span> <span class="s">text/css</span> <span class="s">application/xml</span> <span class="s">text/javascript</span><span class="p">;</span>
</span><span class='line'>  <span class="kn">client_max_body_size</span> <span class="s">100M</span><span class="p">;</span> <span class="c1">#關係到上傳檔案的上限</span>
</span><span class='line'>  <span class="kn">passenger_root</span> <span class="s">/usr/local/ruby23/lib/ruby/gems/2.3.0/gems/passenger-5.1.1</span><span class="p">;</span> <span class="c1">#Passenger Gem 的根目錄，會因為使用的 Ruby 版本與 Passenger 版本變化</span>
</span><span class='line'>  <span class="kn">passenger_max_pool_size</span> <span class="mi">16</span><span class="p">;</span> <span class="c1"># 最大同時可以存在的 Rails App 行程數，請依照系統的記憶體大小計算，一般應該是 &quot;(總記憶體 x 0.75) / 單一 Rails App 使用記憶體&quot;，例如 4GB 的機器，單一 Rails App 記憶體約 150 就是 ``` 4096 * 0.75 / 150  = 20 ```</span>
</span><span class='line'>  <span class="kn">server{</span>
</span><span class='line'>    <span class="s">server_name</span> <span class="s">_</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">location</span> <span class="s">/</span><span class="p">{</span>
</span><span class='line'>      <span class="kn">return</span> <span class="mi">404</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span><span class="c1"># 對應不屬於任何 Virtual Host 的請求，在這裡返回 404 Not Found 的頁面。</span>
</span><span class='line'>  <span class="k">include</span> <span class="n">valid-vhosts/*.conf</span>; <span class="c1">#在其它檔案中設定 Virtual Host</span>
</span><span class='line'><span class="k">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>以下是 Virtual Host 的設定</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='nginx'><span class='line'><span class="k">server{</span>
</span><span class='line'>  <span class="s">server_name</span> <span class="s">5xruby.tw</span><span class="p">;</span> <span class="c1">#Virtual Host 的主機名稱</span>
</span><span class='line'>  <span class="k">root</span> <span class="s">/home/5xruby/5xruby.tw/current/public</span><span class="p">;</span> <span class="c1">#務必設定為 App 的 Public 目錄</span>
</span><span class='line'>  <span class="k">passenger_enabled</span> <span class="no">on</span><span class="p">;</span> <span class="c1">#開啟 Passenger</span>
</span><span class='line'>  <span class="k">rails_env</span> <span class="s">production</span><span class="p">;</span> <span class="c1"># 設定 Rails App Stage</span>
</span><span class='line'>  <span class="k">passenger_ruby</span> <span class="s">/usr/local/ruby23/bin/ruby</span><span class="p">;</span> <span class="c1">#如果這個 App 和 Passenger 使用的 Ruby 版本不同的話就需要指定</span>
</span><span class='line'>  <span class="k">access_log</span> <span class="s">logs/5xruby-access.log</span><span class="p">;</span>
</span><span class='line'>  <span class="k">error_log</span> <span class="s">logs/5xruby-err.log</span><span class="p">;</span>
</span><span class='line'>  <span class="k">location</span> <span class="p">~</span> <span class="sr">^/assets/</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1"># 讓瀏覽器快取靜態 Asset Pipeline 檔案的設定</span>
</span><span class='line'>    <span class="kn">expires</span> <span class="s">1y</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">add_header</span> <span class="s">Cache-Control</span> <span class="s">public</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">add_header</span> <span class="s">ETag</span> <span class="s">&quot;&quot;</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">break</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="k">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>設定 systemd 啟動檔</h3>

<ul>
<li>編輯  /lib/systemd/system/nginx.service</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='nginx'><span class='line'><span class="k">[Unit]</span>
</span><span class='line'><span class="s">Description=The</span> <span class="s">NGINX</span> <span class="s">HTTP</span> <span class="s">and</span> <span class="s">reverse</span> <span class="s">proxy</span> <span class="s">server</span>
</span><span class='line'><span class="s">After=syslog.target</span> <span class="s">network.target</span> <span class="s">remote-fs.target</span> <span class="s">nss-lookup.target</span>
</span><span class='line'>
</span><span class='line'><span class="s">[Service]</span>
</span><span class='line'><span class="s">Type=forking</span>
</span><span class='line'><span class="s">PIDFile=/var/run/nginx.pid</span>
</span><span class='line'><span class="s">ExecStartPre=</span>  <span class="s">/usr/local/nginx/sbin/nginx</span> <span class="s">-t</span>
</span><span class='line'><span class="s">ExecStart=</span>  <span class="s">/usr/local/nginx/sbin/nginx</span>
</span><span class='line'><span class="s">ExecReload=/bin/kill</span> <span class="s">-s</span> <span class="s">HUP</span> <span class="nv">$MAINPID</span>
</span><span class='line'><span class="s">ExecStop=/bin/kill</span> <span class="s">-s</span> <span class="s">QUIT</span> <span class="nv">$MAINPID</span>
</span><span class='line'><span class="s">PrivateTmp=true</span>
</span><span class='line'>
</span><span class='line'><span class="s">[Install]</span>
</span><span class='line'><span class="s">WantedBy=multi-user.target</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>以 root 身份輸入 <code>systemctl enable nginx</code> 設定開機自動啟動</li>
<li>輸入 <code>/usr/local/nginx/sbin/nginx -t</code> 測試設定檔正確與否</li>
<li><code>systemctl start nginx</code> 啟動，可以再透過 <code>systemctl status nginx</code> 觀察啟動情形</li>
</ul>


<h3>Logrotate 設定</h3>

<p>如果在前面的 Virtual  Host 設定中有設定 access_log 或 error_log 的話，就必需要設定 <a href="http://linux.vbird.org/linux_basic/0570syslog.php#rotate">Logrotate</a> 來定期輪替 Nginx log，輪替的設定如下。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='nginx'><span class='line'><span class="k">/usr/local/nginx/logs/*.log</span> <span class="p">{</span>
</span><span class='line'>    <span class="kn">missingok</span>
</span><span class='line'>    <span class="s">size=20M</span> <span class="c1">#單檔超過 20M 為條件</span>
</span><span class='line'>    <span class="s">compress</span> <span class="c1">#壓縮舊檔案</span>
</span><span class='line'>    <span class="s">rotate</span> <span class="mi">10</span>
</span><span class='line'>    <span class="s">notifempty</span>
</span><span class='line'>    <span class="s">sharedscripts</span>
</span><span class='line'>    <span class="s">postrotate</span>
</span><span class='line'>    <span class="s">test</span> <span class="s">!</span> <span class="s">-f</span> <span class="s">/var/run/nginx.pid</span> <span class="s">||</span> <span class="s">kill</span> <span class="s">-s</span> <span class="s">USR1</span> <span class="s">`cat</span> <span class="s">/var/run/nginx.pid`</span> <span class="c1">#讓 Nginx 重新開啟 Log 檔</span>
</span><span class='line'>    <span class="s">endscript</span>
</span><span class='line'><span class="err">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>對 Rails 產生的 Log 也可以比照辦理</p>

<h3>Iptables 設定</h3>

<p>現在的 RHEL 系 OS 通常都預設使用 Firewalld 做為系統防火牆，在此先改回筆者比較熟悉的 Iptables</p>

<ul>
<li>yum remove firewalld</li>
<li>yum install iptables-services</li>
<li>編輯 /etc/sysconfig/iptables</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='nginx'><span class='line'><span class="k">*filter</span>
</span><span class='line'><span class="p">:</span><span class="s">INPUT</span> <span class="s">ACCEPT</span> <span class="s">[0:0]</span>
</span><span class='line'><span class="p">:</span><span class="s">FORWARD</span> <span class="s">ACCEPT</span> <span class="s">[0:0]</span>
</span><span class='line'><span class="p">:</span><span class="s">OUTPUT</span> <span class="s">ACCEPT</span> <span class="s">[0:0]</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-m</span> <span class="s">state</span> <span class="s">--state</span> <span class="s">RELATED,ESTABLISHED</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-s</span> <span class="mi">127</span><span class="s">.0.0.1</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-p</span> <span class="s">icmp</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-i</span> <span class="s">lo</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-p</span> <span class="s">tcp</span> <span class="s">-m</span> <span class="s">state</span> <span class="s">--state</span> <span class="s">NEW</span> <span class="s">-m</span> <span class="s">tcp</span> <span class="s">--dport</span> <span class="s">ssh</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-p</span> <span class="s">tcp</span> <span class="s">-m</span> <span class="s">state</span> <span class="s">--state</span> <span class="s">NEW</span> <span class="s">-m</span> <span class="s">tcp</span> <span class="s">--dport</span> <span class="s">http</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">-A</span> <span class="s">INPUT</span> <span class="s">-p</span> <span class="s">tcp</span> <span class="s">-m</span> <span class="s">state</span> <span class="s">--state</span> <span class="s">NEW</span> <span class="s">-m</span> <span class="s">tcp</span> <span class="s">--dport</span> <span class="s">https</span> <span class="s">-j</span> <span class="s">ACCEPT</span>
</span><span class='line'><span class="s">COMMIT</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>systemctl start iptables</li>
</ul>


<p>到此為止就完成了基本 Rails Stack 的設定。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Install Ruby / Rails / Passenger / PostgreSQL Stack in RHEL and variant OS (前篇)]]></title>
    <link href="http://ryudo.tw/blog/2017/01/24/install-ruby-rails-passenger-postgresql-into-rhel-2017/"/>
    <updated>2017-01-24T15:10:00+08:00</updated>
    <id>http://ryudo.tw/blog/2017/01/24/install-ruby-rails-passenger-postgresql-into-rhel-2017</id>
    <content type="html"><![CDATA[<p>在敝公司<a href="https://5xruby.tw/">五倍紅寶石</a>每期的<a href="https://5xruby.tw/talks/ruby-on-rails2016-4">RUBY ON RAILS 從零開始</a>課程中，常常會遇到學員詢問如何在 <a href="https://www.linode.com/">Linode</a> 或 <a href="https://www.digitalocean.com">Digital Ocean</a> 這類 VPS 平台中安裝 Ruby / Rails Stack 的相關問題，以下的文章將簡介在目前最新版的 RHEL 系 OS 上安裝 Rails Stack 的步驟。</p>

<p>本篇文章的 Rails Stack 包含：</p>

<ol>
<li>系統上可以跑多重版本的 Ruby</li>
<li>Rails 5</li>
<li>PostgreSQL 9.6</li>
<li>使用 Passenger 為 Application Server，Nginx 為 Web Frontend Server</li>
</ol>


<p>本篇文章適用的 Linux Distribution：</p>

<ol>
<li>RedHat Enterprise 7</li>
<li>CentOS 7</li>
<li>Fedora 24+</li>
<li>其它 RHEL 衍生的，以 systemd 為啟動系統的 Linux Distribution 們 (理論上)</li>
</ol>


<p>從乾淨的 OS 開始，步驟大致如下：</p>

<ul>
<li>安裝必要套件</li>
<li>安裝 PGDG Repo &amp; PostgreSQL</li>
<li>編譯 Ruby</li>
<li>安裝與編譯 Passenger / Nginx Extension</li>
<li>編譯 Nginx</li>
<li>啟動設定</li>
<li>Logrotate 設定</li>
</ul>


<p>注意：以下所有步驟皆需以 root 身份或 sudo 執行</p>

<h3>安裝必要套件</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='bash'><span class='line'>yum groupinstall <span class="s2">&quot;Development Tools&quot;</span>，
</span></code></pre></td></tr></table></div></figure>


<p>如果是 Fedora 的話，通常還會有 &#8220;C Development Tools and Libraries&#8221; 和 &#8220;D Development Tools and Libraries&#8221; 兩種</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='bash'><span class='line'>yum install v8-devel v8 screen libmcrypt-devel wget libxslt-devel libxml2-devel gdbm-devel libffi-devel zlib-devel openssl-devel libyaml-devel readline-devel curl-devel  pcre-devel git memcached-devel valgrind-devel ImageMagick-devel ImageMagick npm geoip-devel pcre-devel gd-devel openssl-devel
</span></code></pre></td></tr></table></div></figure>


<h4>套件說明：</h4>

<p>主要是針對編譯 Ruby 所需，以及其它常見的 RubyGem 如 RMagick 或是 Asset Pipeline 編譯 JS 所需要的套件等。</p>

<h3>安裝 PGDG Repo / PostgreSQL</h3>

<h4>什麼是 <a href="https://yum.postgresql.org/repopackages.php">PGDG</a></h4>

<p>PGDG (PostgreSQL Global Development Group) 是 PostgreSQL (以下簡稱 PgSQL) 的開發單位的簡稱，PGDG Repo 是 PgSQL 的官方為各大 Linux Distribution 提供的套件庫。</p>

<h4>安裝步驟：</h4>

<p>在<a href="https://yum.postgresql.org/repopackages.php">這邊</a>找到對應的 PgSQL 版本與 Distribution 的對應 RPM Url 後，在 Console 下：</p>

<p>以 Fedora 25 + PgSQL 9.6 為例：</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='bash'><span class='line'>rpm -Uvh https://download.postgresql.org/pub/repos/yum/9.6/fedora/fedora-25-x86_64/pgdg-fedora96-9.6-3.noarch.rpm
</span></code></pre></td></tr></table></div></figure>


<p>然後安裝 PgSQL 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>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>yum install postgresql96 postgresql96-devel postgresql96-server postgresql96-libs postgresql96-contrib
</span></code></pre></td></tr></table></div></figure>


<p>請注意如果你安裝的不是 9.6 的話，請將上面的 96 改成對應的版號即可</p>

<h3>編譯 Ruby</h3>

<p>這邊不使用 rvm 或 rbenv 等 Ruby 版本管理套件，而是採用將不同的 Ruby 版本安裝到不同路徑的方式來解決可能在 Server 上同時運行多版本 Ruby 的需求。</p>

<p>路徑設定原則：</p>

<p>例如 2.3 就安裝到 <code>/usr/local/ruby23</code>，2.4就在 <code>/usr/local/ruby24</code> 以此類推</p>

<p>流程：</p>

<ul>
<li>下載 CRuby source code</li>
</ul>


<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='bash'><span class='line'><span class="nb">cd</span> /usr/src <span class="o">&amp;&amp;</span> wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.bz2
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>解壓縮</li>
</ul>


<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='bash'><span class='line'>tar -jxvf ruby-2.3.3.tar.bz2
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>configure</li>
</ul>


<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='bash'><span class='line'><span class="nb">cd </span>ruby-2.3.3 <span class="o">&amp;&amp;</span> ./configure --prefix<span class="o">=</span>/usr/local/ruby23
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>make</li>
</ul>


<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='bash'><span class='line'>make <span class="o">&amp;&amp;</span> make install
</span></code></pre></td></tr></table></div></figure>


<p>其它版本可以比照辦理。</p>

<h3>安裝 Passenger 與 Nginx Module</h3>

<ul>
<li>在執行任何 Ruby 指令前請記得設定系統路徑到要使用 Ruby 版本的 bin 目錄，例如：</li>
</ul>


<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='bash'><span class='line'><span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/usr/local/ruby23/bin:
</span></code></pre></td></tr></table></div></figure>


<p>或是把以上內容加到 <code>~/.bash_profile</code> 的尾端，讓每次登入時自動執行。</p>

<ul>
<li>安裝 bundler &amp; passenger Gem</li>
</ul>


<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='bash'><span class='line'>gem install passenger bundler
</span></code></pre></td></tr></table></div></figure>


<p>此時要注意安裝的 Passenger 版號，進入 Passenger 目錄編譯 Passenger Nginx Module，以 Ruby 2.3 和 Passenger 5.1.1 為例：</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='bash'><span class='line'><span class="nb">cd</span> /usr/local/ruby23/lib/ruby/gems/2.3.0/gems/passenger-5.1.1/
</span><span class='line'>rake nginx
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>下載 Nginx 源碼並使用編譯好的 Passenger Module 編譯 (以 1.10.1 版為例)</li>
</ul>


<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='bash'><span class='line'><span class="nb">cd</span> /usr/src <span class="o">&amp;&amp;</span> wget http://nginx.org/download/nginx-1.10.1.tar.gz
</span><span class='line'>
</span><span class='line'>tar -zxvf nginx-1.10.1.tar.gz <span class="o">&amp;&amp;</span> <span class="nb">cd </span>nginx-1.10.1
</span><span class='line'>
</span><span class='line'>./configure --with-http_v2_module --with-http_ssl_module --prefix<span class="o">=</span>/usr/local/nginx --with-http_image_filter_module --with-http_gzip_static_module --with-http_secure_link_module --with-http_stub_status_module --add-module<span class="o">=</span><span class="s2">&quot;/usr/local/ruby23/lib/ruby/gems/2.3.0/gems/passenger-5.1.1/src/nginx_module&quot;</span>
</span><span class='line'>
</span><span class='line'>make <span class="o">&amp;&amp;</span> make install <span class="c">#這裡會將 Nginx 安裝到 /usr/local/nginx 下</span>
</span></code></pre></td></tr></table></div></figure>


<p>至此為止 Nginx 已設定完成，後續操作請看<a href="http://ryudo.tw/blog/2017/02/02/install-ruby-rails-passenger-postgresql-into-rhel-2017-02/">下篇</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RubyKaigi 2016]]></title>
    <link href="http://ryudo.tw/blog/2016/09/26/my-rubykaigi-2016-tour/"/>
    <updated>2016-09-26T17:35:00+08:00</updated>
    <id>http://ryudo.tw/blog/2016/09/26/my-rubykaigi-2016-tour</id>
    <content type="html"><![CDATA[<script async src="http://ryudo.tw//platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>今年的 RubyKaigi 2016 是我從 2013 以來，連續第四年參加的 RubyKaigi，前面三次除了去年以外都有留下一些紀錄（<a href="http://ryudo.tw/blog/2013/06/07/rubykaigi2013-lt/">2013</a>, <a href="http://ryudo.tw/blog/2014/09/28/shibuya-it-tour-by-igaiga555/">2014</a>）</p>

<h3>RubyKaigi 是神馬？</h3>

<p><a href="http://rubykaigi.org">RubyKaigi</a> 是日本最大的 Ruby 語言年度研討會，Kaigi 就是日文漢字的「会議」，在日本除了全國性的這個 RubyKaigi 外，也有很多地區性（Regional）的 RubyKaigi，例如去年底我受邀參加的<a href="http://ryudo.tw/blog/2015/11/18/oedork-and-rwc/">大江戶 RubyKaigi</a> 等。</p>

<h3>今年的行程</h3>

<p>和去年一樣，今年的 RubyKaigi 行除了參加 conf 外，同時也是敝公司的年度員工旅遊，所以提前在 conf 前一週的 9/3 出發到大阪，9/6 移師到京都，然後在 Kaigi 結束後的隔天 9/11 回台。</p>

<p>團員的構成是包含我在內的 12 名<a href="http://5xRuby.tw">五倍紅寶石</a>正職員工以及 2 位實習生（是的，你沒看錯，在本公司實習就是有這種福利）以及公司的講師和合作夥伴共 4 位一共 18 人。</p>

<p><img src="http://ryudo.tw/images/2016-rubykaigi/1st-Day_4735.jpg" alt="" /></p>

<p>行程大概是長這樣：</p>

<ul>
<li>9/3 出發，晚上逛街</li>
<li>9/4 宅宅日本橋調查兵團組 &amp; USJ 組</li>
<li>9/5 京女大交流 &amp; 神戶.rb 交流</li>
<li>9/6 移師京都 &amp; 嵐山遊</li>
<li>9/7 二条城 &amp; 川崎重工參訪 &amp; pre-Party</li>
<li>9/8 DAY1 &amp; Official Party</li>
<li>9/9 DAY2 &amp; 一次會 &amp; <a href="https://goo.gl/Dpq6tL">#RubyKaraoke</a></li>
<li>9/10    DAY3 &amp; After Party</li>
<li>9/11    歸國</li>
</ul>


<p>個別行程的內容由於已經有同事寫出遊記，在此就不特別贊述，可以參考下面的連結：</p>

<ul>
<li><a href="http://blog.frost.tw/posts/2016/09/17/the-new-vision-after-rubykaigi2016/">蒼時</a></li>
<li><a href="http://lctseng-blog.logdown.com/posts/924824-rubykaigi-2016">@lctseng</a></li>
<li><a href="https://goo.gl/tA8qUL">Roy</a></li>
<li><a href="https://goo.gl/PQurTH">Nina</a></li>
<li><a href="https://goo.gl/JXs9Dn">Yusheng</a></li>
<li><a href="https://goo.gl/7oR3JM">Cat</a></li>
<li><a href="https://goo.gl/nvBUZj">Alan</a></li>
<li><a href="https://goo.gl/QvMz2D">Treekey</a></li>
<li><a href="https://goo.gl/V8tXhM">Sabrina</a></li>
<li><a href="https://goo.gl/t5sm5t">孟穎</a></li>
</ul>


<h3>會場</h3>

<p>會場「<a href="http://www.icckyoto.or.jp/">国立京都国際会館</a>」應該是今年最大的亮點，很可能也是未來永遠無法超越的經典了，不愧是簽訂過「<a href="https://zh.wikipedia.org/wiki/%E4%BA%AC%E9%83%BD%E8%AE%AE%E5%AE%9A%E4%B9%A6">京都議定書</a>」的地方，除了國際級的內裝和座位數（超過 1700）外，最厲害的就是會場旁的庭院，會有種讓人誤以為是在山中而不是都會區的錯覺。</p>

<p><img src="http://ryudo.tw/images/2016-rubykaigi/IMG_1345.jpg" alt="" />
<img src="http://ryudo.tw/images/2016-rubykaigi/IMG_1346.jpg" alt="" /></p>

<p>庭院區的後面還有一個很大的池子，目測大概和花蓮的鯉魚潭差不多的程度，以後有機會一定還要再來看看。</p>

<h3>議程</h3>

<p>和往年一樣陣容堅強的<a href="http://rubykaigi.org/2016/schedule/">議程</a>，特色是沒有 Rails 功能直接相關的議程，然後 mruby 相關的議程很多，我個人還蠻期待 <a href="http://rubykaigi.org/2016/presentations/udzura.html">haconiwa</a> 這個 LXC 實作的，除了和往年一樣提供日翻英口譯外，今年甚至有幾位日本講者像 @_ko1 和前面提到的 haconiwa 是直接以英文發表，對於一個在日本舉辦的會議來說算是相當不簡單的事情，不過最後總召（日本這邊叫 Chief Organizer）松田大神也在閉幕式時提到因為要節省口譯費用所以鼓勵日本講者們多多以英文發表。</p>

<p>@youchan 的「<a href="http://rubykaigi.org/2016/presentations/youchan.html">Isomorphic web programming in Ruby</a>」主要是繼去年的「<a href="http://rubykaigi.org/2015/presentations/youchan">Writing web application in Ruby</a>」也就是用 Opal = Ruby 語法寫 JS 和 React 後，再加上另一個新的 Gem 去做 Isomorphic，聽起來很炫，不過個人目前還無法突破用 Ruby 語法寫 JS 這個關卡就是。</p>

<p>第二天的 <a href="http://rubykaigi.org/2016/presentations/searls.html">Keynote</a> 講者 Justin Searls 之前就聽 Juanito 推薦過他好多次，除了內容外，演講技巧和 Slide 也都非常棒，可惜今年來不及邀請他在 RubyConf Taiwan 發表了。</p>

<p>這次和前幾年一樣也都有台灣人的議程上榜，其中也有我們家蒼時，和 iCHEF 的 John，今年會場的台灣會眾加本公司大概有 30 上下，應該是除了日本美國以外人數排第三的國家。</p>

<h3>週邊活動</h3>

<p>和過往一樣，RubyKaigi 這一週從會前一天（週三）到週六，每天晚上都有無限制的酒食 Party，不過和過往不同的地方是&#8211;大部份的 Party 都要自費，主要是因為今年超低的票價（Early Bird：10,000 Yen，去年同樣票種是 25,000）無法包山包海之故，唯三免費的是第二天由 Misoca 和 Agile Works 主辦的兩場並行 Party 和我最期待的 <a href="https://goo.gl/Dpq6tL">#RubyKaraoke</a>（感謝贊助商 <a href="http://www.drecom.co.jp/">Drecom</a>），這次因為沒有終電拘束器（旅館在 KTV 場地附近），最後唱到了 3:30，結束後還一起去吃拉麵，好不開心。</p>

<iframe src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fryudoawaru%2Fposts%2F10206717368805302&width=500" width="500" height="588" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true"></iframe>


<p>最後的 After Party 還特地請我們家 Nina 妹妹上去發表 LT 推一下即將在 12/2~3 舉辦的 RubyConf Taiwan 2016！</p>

<blockquote class="twitter-tweet" data-lang="zh-tw"><p lang="en" dir="ltr">The RubyKaigi 2016 After Party &amp; Lightning Talks! <a href="https://twitter.com/hashtag/rubykaigi?src=hash">#rubykaigi</a> (@ Gion in Kyoto, Kyōto) <a href="https://t.co/6tQD51aC9V">https://t.co/6tQD51aC9V</a> <a href="https://t.co/gVz4vB4ekM">pic.twitter.com/gVz4vB4ekM</a></p>&mdash; tzwm (@tzwm) <a href="https://twitter.com/tzwm/status/774582538723553282">2016年9月10日</a></blockquote>




<blockquote class="twitter-tweet" data-lang="zh-tw"><p lang="en" dir="ltr">. @itsmeninayeh &#39;s presentation! <a href="https://twitter.com/hashtag/rubykaigi?src=hash">#rubykaigi</a> <a href="https://t.co/NdYguHWyyW">pic.twitter.com/NdYguHWyyW</a></p>&mdash; Koichi ITO (@koic) <a href="https://twitter.com/koic/status/774581356542033920">2016年9月10日</a></blockquote>


<h3>總結</h3>

<p>從 2013 以來每年都參加 RubyKaigi，每年都有亮點，但對我自己來說最大的變化是每年的同行陣容都不一樣：</p>

<ul>
<li>2013：自己當 LT 講者和社群的朋友同行</li>
<li>2014：和同事、朋友以及一群被 Heroku 與日本社群朋友贊助的 Rails Girls 們同行</li>
<li>2015：變成公司旅遊行程，團員 6 名</li>
<li>2016：團員變成去年的 3 倍（今年不是五倍嗎？）</li>
</ul>


<p>每年的陣容也反應了人生階段的演變，目前的遺憾是還沒有機會作為正式議程的講者上台，希望未來還有機會。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[用 letsencrypt-cli Rubygem 在 Nginx 上實裝 Let's Encrypt 免費 SSL 服務]]></title>
    <link href="http://ryudo.tw/blog/2016/02/23/apply-letsencrypt-ssl-under-nginx/"/>
    <updated>2016-02-23T12:40:00+08:00</updated>
    <id>http://ryudo.tw/blog/2016/02/23/apply-letsencrypt-ssl-under-nginx</id>
    <content type="html"><![CDATA[<p><a href="https://letsencrypt.org/">Let&#8217;s Encrypt</a> 是一個（目前）免費的 SSL 服務，它和其它 SSL 服務商的不同，除了免費之外，就是它需要透過一些方式來驗證你對網站的所有權來申請與更新憑證，而且一次憑證的有效期限（目前）最大是 90 天，也就是說你要持續定期的更新憑證才能使用。</p>

<h3>Let&#8217;s Encrypt 運作原理</h3>

<p>如<a href="https://letsencrypt.org/howitworks/technology/">官網</a>所示，比較白話一點的流程大概是：</p>

<ol>
<li>用指令向 Let&#8217;s Encrypt 要求產生驗證 host example.com 的檔案</li>
<li>LE 給你驗證檔案</li>
<li>你將檔案放在 http://example.com/.well-known/acme-challenge 下</li>
<li>LE 會發出 HTTP Request 驗證該檔案是否存在前述 URL 下</li>
<li>如果有，則發放證書</li>
</ol>


<p>今天要講的是用 Nginx 加上<a href="https://github.com/zealot128/ruby-letsencrypt-cli">Let&#8217;s Encrypt Ruby Cli Rubygem</a>的驗證方法</p>

<h4>為何要使用 ruby-letsencrypt-cli 而非 LE 官方版本 CLI</h4>

<ul>
<li>不需要 root 權限即可執行</li>
<li>函式庫相依性較簡單</li>
<li>功能相對單純</li>
</ul>


<h4>安裝 Let&#8217;s Encrypt Ruby Cli</h4>

<p>安裝方式就是單純的 <code>gem install letsencrypt-cli</code> 即可。</p>

<h4>事前準備</h4>

<ul>
<li>安裝好 Gem</li>
<li>預備好以下目錄：

<ul>
<li>key-directory：放 key 的地方</li>
<li>webroot-path：在前述的 step 3 給 LE 做 acme-challenge 的檔案放置目錄</li>
<li>放置 account_key 的目錄，通常會放在你的 home</li>
<li>在你要生 SSL 證書的網站的 Virtual Host 的設定內放置以下設定並重啟 nginx，讓 LE 可以用 <code>http://example.com/.well-known/acme-challenge</code> 的網址認證 ：</li>
</ul>
</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<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=''><span class='line'>server{
</span><span class='line'>  ...
</span><span class='line'>  location '/.well-known/acme-challenge/' {
</span><span class='line'>    default_type "text/plain";
</span><span class='line'>    alias /var/www/acme-challenge/;
</span><span class='line'>  }
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>


<ul>
<li>註冊 account，執行：<code>letsencrypt-cli register xxx.ooo.com</code> ，產生帳號密鑰 account_key.pem</li>
<li>讓 LE 認證你的網站，執行：<code>letsencrypt-cli authorize --webroot-path /var/www/acme-challenge example.com</code></li>
<li>生成 key：<code>cd key-directory &amp;&amp; letsencrypt-cli cert example.com</code>，會生成：cert.pem  chain.pem  fullchain.pem  key.pem 等四個檔案</li>
<li>設定 Nginx 在 Virtual Host 使用剛才產生的檔案：</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>server{
</span><span class='line'>   ...
</span><span class='line'>   ssl_certificate key-directory/fullchain.pem;
</span><span class='line'>   ssl_certificate_key key-directory/key.pem;
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>


<ul>
<li>重啟 Nginx，完成</li>
</ul>


<h4>更新 Key</h4>

<p>執行</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='bash'><span class='line'>letsencrypt-cli manage --days-valid 30 -a :account_key.pem的位置: --webroot-path /var/www/acme-challenge --key-directory /etc/letsencrypt/live :你要更新的 hosts 以空白分隔:
</span></code></pre></td></tr></table></div></figure>


<p>建議把它加到 crontab 中定時執行</p>

<h3>問題整理：</h3>

<ul>
<li>執行 letsencrypt-cli 出現 <code>Acme::Client::Error::Malformed</code> 錯誤：請降級你的 json-jwt  gem 到 1.5.2</li>
<li>出現 Account Key Note Found：命令列加上 <code>-a :account_key.pem的位置:</code></li>
<li>openssl 版本太舊：openssl 版本建議在 1.0.2 以上，特別是如果要跑 http/2 的話</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[將 5xruby.tw 升級到 Rails 5.0.0.beta2]]></title>
    <link href="http://ryudo.tw/blog/2016/02/05/upgrade-5xruby-to-5-dot-0-beta/"/>
    <updated>2016-02-05T15:01:00+08:00</updated>
    <id>http://ryudo.tw/blog/2016/02/05/upgrade-5xruby-to-5-dot-0-beta</id>
    <content type="html"><![CDATA[<p>最近將敝公司 5xruby.tw 的官網的 Rails 版本升級到 5.0.0.beta2，具體的升級 commit 主要在 <a href="https://github.com/5xRuby/5xruby.tw/commit/5d7587d341e63bb0260c52410dafd4514c38bbc4">5d7587d</a>，以下是一些步驟說明：</p>

<ol>
<li>確認 Ruby 版本在 2.2.1 以上，最好是 2.3</li>
<li>在 Gemfile 設定 rails 的版本為 5.0.0.beta2</li>
<li>同時，確認所有安裝的 Rubygem 是否需要升級，將版號設定好</li>
<li>執行 <code>bundle update</code></li>
<li>先執行 <code>rails update</code> 確認是否每個檔案都需要更改，先讓每個檔案都被覆寫到，再回頭看 diff 進行必要修改</li>
</ol>


<p>需要配合升級的 RubyGem</p>

<ol>
<li>kaminari: 請用 Github 上的 Master branch</li>
<li>simple_form: 請使用最新版 3.2.1</li>
<li>acts-as-taggable-on: 一定要用 Master branch，即使版號看起來一樣</li>
<li>rack-mini-profiler: Master branch</li>
<li>Rails 相關的 Asset Rubygems</li>
<li>Capistrano 升級後配合修改 Capfile 中的版號</li>
</ol>


<p>這次升級比預料中平穩，沒有花很多時間就完成了。</p>

<p>以上</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在 OSX 下升級 Homebrew 安裝的 PostgreSQL(dump 版)]]></title>
    <link href="http://ryudo.tw/blog/2016/02/02/upgrade-postgresql-on-osx/"/>
    <updated>2016-02-02T15:28:00+08:00</updated>
    <id>http://ryudo.tw/blog/2016/02/02/upgrade-postgresql-on-osx</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<p>繼上一篇的 <a href="http://ryudo.tw/blog/2015/02/15/upgrade-pgsql-from-93-to-94/">在 Mac / Homebrew 下升級 PostgreSQL 從 9.3 到 9.4</a> 之後，最近由於更換筆電 / 不想用 TimeMachine 加上剛好 PostgreSQL 9.5 發佈的關係，必需重新用 Homebrew 安裝 PostgreSQL 9.5，本來使用了前篇所介紹的方式來移轉舊版 PostgreSQL 9.4 的資料檔，但是很神奇地發現在所有 Rails App 的 DB 中的 schema_migration 表的資料通通遺失了，所以就必需要使用另一種方式來升級。</p>

<h3>升級的方式</h3>

<p>一般來說有以下兩種</p>

<ul>
<li><p>從資料檔案 (raw data file) 轉移</p>

<p>不像 MySQL，PostgreSQL 每個版本的 raw data file 都是不相容的（註：MySQL 也要看 Storage Engine），所以當升級新版的時候是不能直接套用的，PostgreSQL 也提供了 pg_upgrade 指令來幫助升級，這也是前一篇的主題。</p></li>
<li><p>使用 SQL 檔案轉移</p>

<p>使用 pg_dump 或 pg_dumpall 等工具將舊 DB Dump 成 SQL 指令的格式，再輸入到新 DB 上即可></p></li>
</ul>


<h3>流程</h3>

<ol>
<li><p>更改資料檔目錄</p>

<p>Homebrew 預設的資料檔目錄在 <code>/usr/local/var/postgres</code> 請把它移到另一個目錄去</p></li>
<li><p>自舊版 PostgreSQL Dump SQL 檔案</p>

<p>如果還沒有升級新版前，就直接執行</p>

<p><code>
pg_dumpall -c -f 目的檔案名
</code></p>

<p>即可，選項 -c 是在 dump 檔中附加移除既存 DB 的指令，可視個人需求決定要不要加。</p>

<p>要是已經升級新版的話，由於 PostgreSQL 套件的發佈者都很貼心的把所有檔案照版本排列，所以可以用以下的指令開啟一個暫時的 PostgreSQL Daemon</p>

<p><code>
/usr/local/Cellar/postgresql/9.4.1/bin/postmaster -D /usr/local/var/postgres94/ -k /tmp/pg94/ -p 8822
</code></p>

<p>選項中 -D 是指定資料檔目錄，-k 是 socket file 的目錄，-p 是 port，要注意這兩者都不能和執行中的新版本重疊，這樣就順利開啟了服務，然後再執行 <code>pg_dumpall -c -p 8822 -h /tmp/pg94</code> 就可以取得 dump SQL 檔了</p></li>
<li><p>自 dump SQL 檔還原到新版資料庫中</p>

<p>在上一步的 dump 指令中就可以用 pipe 一步完成了：</p>

<p><code>pg_dumpall -c -p 8822 -h /tmp/pg94 | psql postgres</code></p></li>
</ol>


<p>以上</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Table Inheritance in PostgreSQL]]></title>
    <link href="http://ryudo.tw/blog/2015/12/31/pgsql-inheritance/"/>
    <updated>2015-12-31T12:17:00+08:00</updated>
    <id>http://ryudo.tw/blog/2015/12/31/pgsql-inheritance</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<p><a href="http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html">Single Table Inheritance</a>（以下簡稱 STI） 是我們在 Rails 常用的一個功能，一般來說 STI 在 Rails 的實現方式如下：</p>

<ol>
<li>一張資料表</li>
<li>多個 ActiveRecord Class 使用這張表</li>
<li>預設用 type 這個欄位來界定這筆紀錄所屬的 class</li>
</ol>


<p>這樣做的好處是子類別可以用父類別的欄位，主要的缺點是在可能會浪費到不需要的欄位；Rails 之所以這樣設計，主要是因為大部份的 RDBMS 系統除了 PostgreSQL 和 Oracle 以外幾乎都沒有實作 Table Inheritance。</p>

<h3>PostgreSQL 的 Table Inheritance</h3>

<p>PostgreSQL 的 Table Inheritance 和 STI 最大的差別在於多表繼承，在官網上就有相當詳細的<a href="http://www.postgresql.org/docs/9.1/static/ddl-inherit.html">介紹</a>，基本上就是在資料表之間實作出繼承的關係，B 表繼承 A 表的話，則：</p>

<ul>
<li>B 表會有所有 A 表的欄位資訊</li>
<li>即使日後 A 表欄位有所變動，也會即時反應到 B 表上</li>
<li>B 表所建立的資料，在查尋 A 表時會全部出現，反之則無</li>
</ul>


<p>接下來我們就來介紹如何在 Rails 中用 PostgreSQL 的 Table Inheritance 來實作 ActiveRecord 的物件繼承。</p>

<h4>期望的 Schema</h4>

<p><img src="http://ryudo.tw/images/pgsql-inheritance/schema.png" alt="" /></p>

<h4>實作</h4>

<p>建立父類別 User</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='bash'><span class='line'>rails g model User
</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>
<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">CreateUsers</span> <span class="o">&lt;</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Migration</span><span class="o">[</span><span class="mi">5</span><span class="o">.</span><span class="mi">0</span><span class="o">]</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">change</span>
</span><span class='line'>    <span class="n">create_table</span> <span class="ss">:users</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:username</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:password</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:type</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">timestamps</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><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">User</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>建立 sub-class Staff</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='bash'><span class='line'>rails g model Staff
</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>
<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="k">class</span> <span class="nc">CreateStaffs</span> <span class="o">&lt;</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Migration</span><span class="o">[</span><span class="mi">5</span><span class="o">.</span><span class="mi">0</span><span class="o">]</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">up</span>
</span><span class='line'>    <span class="n">execute</span> <span class="o">&lt;&lt;-</span><span class="no">SQL</span>
</span><span class='line'><span class="sh">    CREATE TABLE staffs(level integer,CONSTRAINT &quot;PK&quot; PRIMARY KEY (id))</span>
</span><span class='line'><span class="sh">    INHERITS(users)</span>
</span><span class='line'><span class="no">    SQL</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">down</span>
</span><span class='line'>    <span class="n">drop_table</span> <span class="ss">:staffs</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">class</span> <span class="nc">Staff</span> <span class="o">&lt;</span> <span class="no">User</span>
</span><span class='line'>  <span class="nb">self</span><span class="o">.</span><span class="n">table_name</span> <span class="o">=</span> <span class="s1">&#39;staffs&#39;</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>和原本 STI 的行為不同，由於 ActiveRecord Migration 並沒有內建相關功能，所以需要自行撰寫 SQL 式來建立 Staffs 表，在建立時需實際指定繼承自 users 表，並且將額外附加的欄位等屬性設定進去即可。</p>

<p>在 Model 的程式方面，必需指定子類別的資料表，否則 Rails 會按照 STI 預設行為去使用父類別的資料表（users）。</p>

<p>在這個範例中，在 staffs 表建立的資料都會出現在 users 表上，反之則不會。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">User</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="ss">username</span><span class="p">:</span> <span class="s1">&#39;ryudo&#39;</span><span class="p">,</span> <span class="ss">password</span><span class="p">:</span><span class="s1">&#39;12345&#39;</span><span class="p">)</span>
</span><span class='line'><span class="no">Staff</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="ss">username</span><span class="p">:</span><span class="s1">&#39;Jodeci&#39;</span><span class="p">,</span><span class="ss">password</span><span class="p">:</span><span class="s1">&#39;12345&#39;</span><span class="p">)</span>
</span><span class='line'><span class="no">User</span><span class="o">.</span><span class="n">pluck</span><span class="p">(</span><span class="ss">:username</span><span class="p">)</span>
</span><span class='line'>   <span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">4</span><span class="n">ms</span><span class="p">)</span>  <span class="no">SELECT</span> <span class="s2">&quot;users&quot;</span><span class="o">.</span><span class="s2">&quot;username&quot;</span> <span class="no">FROM</span> <span class="s2">&quot;users&quot;</span>
</span><span class='line'> <span class="o">=&gt;</span> <span class="o">[</span><span class="s2">&quot;ryudo&quot;</span><span class="p">,</span> <span class="s2">&quot;Jodeci&quot;</span><span class="o">]</span>
</span><span class='line'><span class="no">Staff</span><span class="o">.</span><span class="n">pluck</span><span class="p">(</span><span class="ss">:username</span><span class="p">)</span>
</span><span class='line'>   <span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">4</span><span class="n">ms</span><span class="p">)</span>  <span class="no">SELECT</span> <span class="s2">&quot;staffs&quot;</span><span class="o">.</span><span class="s2">&quot;username&quot;</span> <span class="no">FROM</span> <span class="s2">&quot;staffs&quot;</span> <span class="no">WHERE</span> <span class="s2">&quot;staffs&quot;</span><span class="o">.</span><span class="s2">&quot;type&quot;</span> <span class="no">IN</span> <span class="p">(</span><span class="s1">&#39;Staff&#39;</span><span class="p">)</span>
</span><span class='line'> <span class="o">=&gt;</span> <span class="o">[</span><span class="s2">&quot;Jodeci&quot;</span><span class="o">]</span>
</span><span class='line'><span class="no">User</span><span class="o">.</span><span class="n">count</span> <span class="c1">#=&gt; 2</span>
</span><span class='line'><span class="no">Staff</span><span class="o">.</span><span class="n">count</span> <span class="c1">#=&gt; 1</span>
</span><span class='line'><span class="no">User</span><span class="o">.</span><span class="n">last</span>
</span><span class='line'>  <span class="no">User</span> <span class="no">Load</span> <span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">6</span><span class="n">ms</span><span class="p">)</span>  <span class="no">SELECT</span>  <span class="s2">&quot;users&quot;</span><span class="o">.</span><span class="n">*</span> <span class="no">FROM</span> <span class="s2">&quot;users&quot;</span> <span class="no">ORDER</span> <span class="no">BY</span> <span class="s2">&quot;users&quot;</span><span class="o">.</span><span class="s2">&quot;id&quot;</span> <span class="no">DESC</span> <span class="no">LIMIT</span> <span class="vg">$1</span>  <span class="o">[[</span><span class="s2">&quot;LIMIT&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="o">]]</span>
</span><span class='line'> <span class="o">=&gt;</span> <span class="c1">#&lt;Staff id: 2, username: &quot;Jodeci&quot;, password: &quot;12345&quot;, type: &quot;Staff&quot;, created_at: &quot;2015-12-31 07:12:16&quot;, updated_at: &quot;2015-12-31 07:12:16&quot;&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<h4>Table Inheritance 會繼承的東西：</h4>

<ul>
<li>欄位資訊：包括預設值或是 NOT NULL，也就是在 SQL 建構式中看到欄位敘述的內容。</li>
<li>父表上的欄位變動：也就是之後在父表上新增刪除修改欄位的變動，會確實的反應到子表上。</li>
</ul>


<h4>Table Inheritance 不會繼承的東西：</h4>

<ul>
<li>欄位資訊以外的全部：包括 Primary Key、Constraint 或是 Index 等。</li>
</ul>


<h4>主鍵重複值問題</h4>

<p>這應該是最大的困擾之一，就是繼承的子表的主鍵是可以和父表的值重複的，例如以下的程式碼是可以正確執行的：</p>

<figure class='code'><figcaption><span>測試title</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="no">User</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="ss">username</span><span class="p">:</span> <span class="s1">&#39;ryudo&#39;</span><span class="p">,</span> <span class="ss">password</span><span class="p">:</span><span class="s1">&#39;12345&#39;</span><span class="p">)</span> <span class="c1">#=&gt; 建立 id 為 1 的 User</span>
</span><span class='line'><span class="no">Staff</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span><span class="ss">username</span><span class="p">:</span><span class="s1">&#39;Jodeci&#39;</span><span class="p">,</span><span class="ss">password</span><span class="p">:</span><span class="s1">&#39;12345&#39;</span><span class="p">)</span> <span class="c1">#=&gt; 建立 id 為 1 的 Staff</span>
</span></code></pre></td></tr></table></div></figure>


<p>這樣在 users 表會真的有兩筆 id 為 1 的紀錄，而且目前無法用資料庫的方式去迴避這個問題，不過由於兩個 id 之間是共用同一個 Sequence，在不指定 id 建立資料的狀況下，id 的值是不會重複的。</p>

<h4>inheritance_column 存廢問題：</h4>

<p>在上面的範例中，我們可以看到原本 STI 的 inheritance_column，也就是 type 這個欄位的存在，原本 STI 的設計是：子類別的資料將會自動在 type 上加上類別名稱，查詢 Staff 時也會預設查詢 type 為 Staff 的資料。</p>

<p>這個設計是因為在資料同屬一張表的前提下，必需用一個欄位去區分類別的關係，而在 Table Inheritance 下，由於每個類別有獨立的資料表，在查詢子類別時已經不需要用 type 這個條件了；但是如果在父類別的資料表查詢時，還是需要用 inheritance_column 去區分出這筆資料所屬的類別，否則所有父類別資料表的資料在 ActiveRecord 中會被視為父類別的資料。</p>

<h4>多表繼承</h4>

<p>其實是有這項功能的，但是目前還沒想到需要使用的場合所以這次就不討論了。</p>

<h3>是否要使用這個功能？</h3>

<h4>好處</h4>

<ul>
<li>比起 ActiveRecord 提供的 STI 更趨近於物件化</li>
<li>由於資料表是物理上的切分，等於是一種 Partitioning，在資料量大的時候可以提升子表的效能</li>
<li>同上，減少欄位或 Index 等資源不必要的浪費</li>
</ul>


<h4>壞處</h4>

<ul>
<li>Rails 預設不支援相關的 Migration 操作，需手動撰寫 SQL</li>
<li>同上，在 Model 的設定上必需客製一些設定</li>
</ul>


<p>以上！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[大江戶 RubyKaigi 05, Asakusa.rb 以及 Ruby World Conference]]></title>
    <link href="http://ryudo.tw/blog/2015/11/18/oedork-and-rwc/"/>
    <updated>2015-11-18T11:03:00+08:00</updated>
    <id>http://ryudo.tw/blog/2015/11/18/oedork-and-rwc</id>
    <content type="html"><![CDATA[<script async src="http://ryudo.tw//platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>這篇 Blog 是我和五倍紅寶石的同事趙子皓於 11 月初一同參加了<a href="http://regional.rubykaigi.org/oedo05/">大江戶 RubyKaigi&#8217;05</a> 以及 <a href="http://2015.rubyworld-conf.org">Ruby World Conference 2015</a> 並分別發表的心得記事。</p>

<h3>逆邀講</h3>

<p>回到今年六月，在準備 RubyConf Taiwan 2015 時，想要邀請連續兩屆來台的 Ruby VM 作者笹田耕一來台發表，但由於他已預定在之後的 RubyConf Portugal 發表所以未能成行，在這信件一來一往中，突然被問到是否可以 11 月的大江戶 RubyKaigi 中發表，驚訝和榮幸之餘想說是一個難得的機會就答應了。</p>

<h3>Ruby World Conference&#8211;投稿與贊助</h3>

<p>和 RubyKaigi 或是 RubyConf 系列的技術研討會不同，這個在 Ruby City — 松江市舉辦的研討會是以「Ruby 的應用和生態」為主，由於敝社原本就是以促進 Ruby 受台灣的程式生態圈愛用為目標，所以就和同事嘗試著投稿看看，沒想到兩個人都順利入選。</p>

<p>除了投稿之外，由於在不論在社群或是公司的方面都受到了日本 Ruby 社群很多照顧，今年本著回饋的心情也贊助了這個活動，也成為了該活動史上第一個海外贊助商。</p>

<h3>行程</h3>

<p>由於大江戶和 RWC 剛好是在前後週，所以我們在大江戶的前一天（11/7）出發，然後在 RWC 結束後一天（11/14）回台。</p>

<h3>大江戶 RubyKaigi</h3>

<p>大江戶 RubyKaigi 是日本眾多<a href="http://regional.rubykaigi.org/">地區性 RubyKaigi</a> 中，歷史最悠久，規模最大的一個，主辦團隊是 Asakusa.rb，這次的場地在東京的中央區舉辦。</p>

<p>今年，也是第五屆的場地是在一個綜合會議中心，除了 7F 的會場外，在 13F 還提供了一個很大的休息區，休息區除了給大家交流之外還提供了會場畫面的 LIVE 直播。</p>

<blockquote class="twitter-tweet" lang="zh-tw"><p lang="ja" dir="ltr">大江戸Ruby会議05の様子ですよぅ 🌊 <a href="https://twitter.com/hashtag/oedo05?src=hash">#oedo05</a> <a href="https://twitter.com/hashtag/asakusarb?src=hash">#asakusarb</a> <a href="https://t.co/lusirCDZiW">pic.twitter.com/lusirCDZiW</a></p>&mdash; 大江戸Ruby会議 (@OedoRubyKaigi) <a href="https://twitter.com/OedoRubyKaigi/status/663176126617948160">2015 11月 8日</a></blockquote>


<p>門票方面，活動門票是 2,000， 不含午餐，After Party 是 5,000 日元，繼承 Asakusa.rb 對外國會眾友善的傳統，外國人和講者全免。</p>

<p>這個活動和一般認知的技術研討會不同的地方，就是它有許多被稱為「生活發表會」的議程；今年的議程除了兩場 Keynote 外，又分為「Ruby Committers&#8217; Lightning Talks」以及「Ninja Talks」兩種，前者顧名思議就是 Ruby Committer 專屬的 LT 時間，後者則是每場 15 分鐘的短講，會眾約 200 多人。</p>

<p>由於我自己的議程是在下午，所以在之前的議程就只有聽到一部份，以下就我自己有聽到的部份做個簡介：</p>

<ol>
<li><p>@usa：<a href="https://speakerdeck.com/unak/talk-about-io">あいおーのはなし（中譯：有關 IO 的話題）</a></p>

<p>講者是 CRuby Windows 版的主要維護者，這篇主要就是在討論 CRuby IO Class 內部實作方式的演進，然後表示他要在 Windows 上 Porting m17n IO 的功能。</p></li>
<li><p>松田明：「<a href="https://speakerdeck.com/a_matsuda/the-kaigi-must-go-on">The Kaigi Must Go On</a>」</p>

<p>講者是今年五月才在 ModernWeb 登台的大神松田明，內容是關於他接任 RubyKaigi 總召的經過，其中提到了原本去年 9 月 RubyKaigi 2014 之前就已經訂好了今年 Kaigi 的場地與時間，但是因為原本的總召角谷大大生了一場病所以中斷了籌備的事情，本來已經打算停辦了，後來由於他實在太常被國內外朋友們詢問是否還會有下一屆的事情，所以最後就自己出來接任總召了，身為 RubyConf.TW 的主辦人真是感到心有戚戚焉。</p></li>
<li><p>中田伸悅：「<a href="https://speakerdeck.com/n0kada/my-best-commits-of-the-year-2015">Best Commits of the year 2015 (仮)</a>」</p>

<p>講者是被稱為 &#8220;Patch Monster&#8221; 的，也是包括 Matz 在內的三位被 Heroku 全職聘用的 Ruby Committer 之一，簡短的內容提到了他在今年最滿意的幾個 Commit。</p></li>
<li><p>小栁真太：「<a href="http://www.slideshare.net/yancyajp/rubyseenfromsqlishbrain-54870167">SQL 脳から見た Ruby（中譯：從 SQL 腦看到的 Ruby）</a>」</p>

<p>講者和我一樣是 PostgreSQL 的同好，裡面講到如何把 SQL 查詢用 Ruby 語法去實作的方式，後面還提到了 PostgreSQL 的專有語法 with 等在 ActiveRecord 的用法，令人腦洞大開，with 相關介紹可以參照阿土伯大大在 Ruby Tuesday 24 的分享。</p></li>
<li><p>西嶋悠貴：「地獄のニューヨーク（紐約）」</p>

<p>講者是新進的 Ruby Committer，也是在國外工作的日本 Rubyist，裡面提到他在紐約的生活，例如怎麼租房子比較省錢，或是交通問題之類，其中最爆笑的一段就是提到當他在住宅遇到搶匪，逃到樓下對面的 PUB 後，酒保竟然跟他說「總之先來一杯再說，我請客」，遺憾的是似乎沒有公開 Slide。</p></li>
<li><p>Kei Sawada：「<a href="https://speakerdeck.com/remore/xiang-jie-burn">詳解Burn</a>」</p>

<p><a href="https://github.com/remore/burn">Burn</a> 是一個可以讓你用 DSL 去寫出任天堂 ROM 的Ruby Gem，去年在 RubyKaigi 就有聽到這個令人印象深刻的議程，這次還加上 telnet mode 的功能，後面還提到了一些 g0v。</p></li>
</ol>


<h4>After Party 和二次與三次會</h4>

<p>這次的 Party 是在知名的 Recruit 公司的員工餐廳舉辦，Party 除了啤酒喝到飽之外，料理陣容也非常豪華，同時還有講者繼續白天的話題，現場又跟大家討論了起來。</p>

<p><img src="http://ryudo.tw/images/201511-OEDO-RWC/thumb_IMG_1686_1024.jpg" alt="" /></p>

<p>Party 結束時大概是 9:30 左右，這時很神奇地就會有一群人自動的聚集在一起等待二次會的來臨，二次會在附近的小 Pub 裡續攤，神奇的是在那個場合中，依然看到 Patch Monster 大大在改 CRuby Source Code XD。</p>

<p>由於二次會時偶然提到很想唱歌，所以就變成在附近的 KTV 進行人生第一次的三次會了 XD，最後在快一點時趕上了終電（最後一班電車）回到旅館。</p>

<p><img src="http://ryudo.tw/images/201511-OEDO-RWC/thumb_IMG_1688_1024.jpg" alt="" /></p>

<h3>Asakusa.rb</h3>

<p>Asakusa.rb 是一個在東京定期舉辦的 Ruby 社群聚會，除了定期聚會以外，也主辦包括前面提到的大江戶，以及每年 RubyKaigi 的 pre-Party，一直以來都很想參加，趁著這次的機會終於可以一嘗宿願。</p>

<p>這次的活動在位於秋葉原附近的<a href="http://www.esm.co.jp">永和 System Management 公司</a>舉辦，活動本身沒有主題演講等，比較像是我們經常在動漫畫裡看到的「部活」，也就是社團活動，大概在晚上七點開始會陸續的有人加入，然後有的人會聚在一起討論或是做自己的事。</p>

<p><img src="http://ryudo.tw/images/201511-OEDO-RWC/thumb_IMG_1700_1024.jpg" alt="" /></p>

<p>大概到了 20:30 ，松田大大就開始請大家自我介紹，大概到 9:30 前部活階段就結束了，接下來就移師到附近的居酒屋舉行二次會，這時松田大大突然對我說；「真正的 Asakusa.rb 現在才開始」，然後就是喝酒聊天了，由於小弟的日文不太輪轉，和大家聊天時松田大大還會很貼心的請大家對我「慢慢地講話」，二次會在大概 12:00 左右結束。</p>

<h3>Ruby World Conference</h3>

<p><img src="http://ryudo.tw/images/201511-OEDO-RWC/RWC-AllSpeakers.jpg" alt="" /></p>

<p>和我們熟知的，針對開發者為主的 RubyConf 系列或是 RubyKaigi 不同，在 Ruby 之父的家鄉島根縣松江市舉辦的 Ruby World Conference 專注在「Ruby 的應用」而非技術。</p>

<p>接著週三就前往羽田機場搭上往出云機場的飛機，在下午四點左右到達了旅館，當天晚上有限定講者和相關人士參加的 pre-Party，是在一間很傳統的日式餐廳舉辦，現場請每位講者上來自我介紹，在場和這次大會的 Keynote Spaker 的 Linda Liukas 相見歡，同時也認識了 RG 松江的主辦團隊，由於其中兩位都是媽媽，話題很快就轉移到育兒經上面 XD。</p>

<p>Pre-Party 結束後，主辦單位很貼心的招待大家搭計程車回到旅館，<del>雖然有二三次會但是因為要準備演講的關係只好 Pass</del>。</p>

<p>隔天就開始了 RWC 的正式議程，開場時先請所有的講者到舞台上合照，接著就是一些地方政治人物像是島根縣長等的致詞，和我們對一般政治人物致詞很「搞威」的印象不同，每位的致詞時間都不超過五分鐘，接下來就是 Matz 的主題演講，這次的演講主題是「Second System Syndrome」，內容和不久前 <a href="https://www.youtube.com/watch?v=cydW3bvUOKQ&amp;index=3&amp;list=PLhKZ4RWngmpDVKgAH_p_X7gtLSGsvmMJj">RubyConf Taiwan 2015 的發表</a>沒有很大的差異。</p>

<p>在單軌兩天的議程中，大會提供了「雙向」的即時口譯服務，接下來的議程由於都在準備講稿和練習（我是第二天倒數第二個講者），幾乎都沒有參加到。</p>

<p>會場是在當地最大的會議中心，除了三樓的演講廳之外，在一樓有一個比演講廳還大的攤位交流區，這裡同時也是會眾午餐以及晚上 Official Party 的場地，攤位的外觀和陳列方式感覺比較像台灣每年五六月間舉辦的 Computex Taipei 這樣的商業展覽，贊助商多半也是在展示自己的技術解決方案之類，沒有看到徵才。</p>

<p>除了交流區的攤位之外，還有一樓的地方旅遊介紹以及 Ruby 拉麵攤位，第二天也帶了一組 Ruby 拉麵回家。</p>

<p>三樓會場外還有一個茶席區，穿著和服的妹妹會用傳統日本茶道的方式磨出抹茶和點心然後再端上來給你。</p>

<p>第一天晚上的 Official Party 當然也是酒類無限暢飲，不過由於一直在交流遞名片聊天的關係所以幾乎沒吃到多少東西（淚～），這個 Party 除了吃吃喝喝外，還有奇妙的島根吉祥物 しまねっこ 出沒。</p>

<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">Meeting with Shimanekko, the mascot of Shimane. 😻 <a href="https://twitter.com/_zzak">@_zzak</a> and my next talk might just be the cat dance. <a href="https://t.co/TkgL6zK6hU">pic.twitter.com/TkgL6zK6hU</a></p>&mdash; Linda Liukas (@lindaliukas) <a href="https://twitter.com/lindaliukas/status/664777586308870144">2015 11月 12日</a></blockquote>


<p>另一個讓我印象很深的地方，就是在會場有寄放衣服與背包的地方，超貼心。</p>

<p>Party 結束後，當然也是有各種二次三次會，不過一樣由於隔天有演講的關係，只能在電腦前看著已經完成發表的同事邊唱 KTV 邊發推😂。</p>

<p><img src="http://ryudo.tw/images/201511-OEDO-RWC/RWC-at-stage.jpg" alt="" /></p>

<p>第二天全部議程結束後，參加了一場需要事先報名的當地特產啤酒燒肉會，接下來一樣有各種續攤，三次會是和一群日本各地的 RG 主辦人一起交流 RG 主辦的經驗等等，拜同行的日文通子皓的幫忙，可以更加輕鬆的交流了，在整個活動期間認識了許多不同城市的 RG 主辦人或教練，真的很開心。</p>

<p>最後一天的早上，在搭車前往機場之前短暫的參觀了 RG 松江，這邊的規模雖然不大，不過會場的佈置很用心，和台灣不一樣的是，一組的配置是 2 位教練配四位學員，等於是台灣兩組的配置，現場還有機器人&#8230;以及 Matz 的立牌。</p>

<p><img src="http://ryudo.tw/images/201511-OEDO-RWC/thumb_IMG_1765_1024.jpg" alt="" />
<img src="http://ryudo.tw/images/201511-OEDO-RWC/thumb_IMG_1775_1024.jpg" alt="" />
<img src="http://ryudo.tw/images/201511-OEDO-RWC/thumb_IMG_1769_1024.jpg" alt="" /></p>

<p>在活動開場後，有 Matz 和 Linda 的致詞，然後我也突然被拉上去致詞了 XD，再度獲得了另一個人生的成就。</p>

<blockquote class="twitter-tweet" lang="zh-tw"><p lang="ja" dir="ltr">台湾より…！！&#10;<a href="https://twitter.com/hashtag/railsgirlsmatsue?src=hash">#railsgirlsmatsue</a> <a href="https://t.co/RBmgXMEH8k">pic.twitter.com/RBmgXMEH8k</a></p>&mdash; yadaita (@yadaita) <a href="https://twitter.com/yadaita/status/665346316826865665">2015 11月 14日</a></blockquote>


<p>最後就在各種趕飛機（出雲 -> 羽田 -> 松山）中結束了整個行程。</p>

<h3>個人成就紀錄</h3>

<p>在這次八天的日本行之中，完成了各種成就，包括：</p>

<ul>
<li>在海外用英文發表技術 &amp; 非技術議題</li>
<li>一週內兩次英文發表</li>
<li>在英文發表前用日文自介</li>
<li>和日本人唱 KTV</li>
<li>二次會 &amp; 三次會</li>
<li>趕終電</li>
</ul>


<h3>感想</h3>

<h4>地方的熱情</h4>

<p>最讓我印象深刻的，就是在日本這個國家，即使是所謂的「田舍」，也就是鄉下地方的人或是政府單位都會很努力的用實際的方式（而不是炒地皮之類）來振興地方的經濟與發展，像 RWC 這種幾乎由地方政府一手主辦的活動就是一個很顯著的例子，為了吸引外國人參加，甚至不惜重本不計成效（畢竟全場只有 15 來個外國人）的提供雙向口譯服務；同時也認識了許多地方的 IT 公司，像是 Matz 以前所屬的 <a href="http://www.netlab.jp">NaCl</a> 等等，很努力的把工作機會帶回自己出身的地方，這點和台灣是很不一樣的；另外松江的消費水平，像是食宿或交通費用（主要是計程車）幾乎和東京沒有什麼差別。</p>

<p>這次也認識了很多地方 RG 活動，像是神戶、松江甚至是以前沒聽過的塩尻等等的主辦人，他們很熱心的將 RG 活動帶到自己的家鄉，同時很多 RG 的教練，例如敝公司的好捧友<a href="http://5xruby.tw/posts/interview-with-igarashi">五十嵐邦明</a>等人，也會從東京自費（或是公司贊助）過去支援；縱觀 RG 的世界各地活動列表可以發現，日本的都市數量是全世界所有國家最多的，活動的頻率也是最頻繁的，可以感受到他們社群之間互相支援的熱情。</p>

<h4>多樣的 Ruby</h4>

<p>一直以來 Ruby 在台灣的認知就是 = Rails，甚至還有很多人把 Rails 誤認為一門語言，雖然我也是從 Rails 入門 Ruby，但是在熟練到一定程度之後就開始著眼於 Rails 或 Web 以外的 Ruby 應用；在這次日本行中又再次見識到 Ruby 的多樣性，以及日本人把 Ruby 的應用延伸到各個層面上的努力，像是這次我就認識了用 Ruby 控制都市瓦斯的系統，或是用 mruby 控製太陽能發電系統的公司，而且在大學也有相關的研究，我想除了 Ruby 是日本發明的語言之外，也包括了日本人對基礎研究的動力，這點和台灣是非常不同的。</p>

<h4>社群的熱情</h4>

<p>有人認為，區別一個國家是否現代化的方式，就是在於其中的人民有沒有一個「對國家主體的認同和想像」而非對個別人物的效忠；我想這點也適用在 Ruby 或是任何的 Open Source 社群上，在日本的 Ruby 社群可以感受到大家對於 Ruby 社群這個主體的認同，各個地區的社群間也會互相支援，例如在我參加 RWC 之前，一直有「這就是很 local 的活動」的刻板印象，不過實際參加之後才發現真的有很多來自東京的 Rubyist 們或公司在會場出沒甚至贊助，包括前面提到的 RG 互相支援，都可以體現出日本的 Ruby 社群有一個共同的認同主體，進而在這個主體之下互相扶持，共同發展的熱情。</p>

<h3>最後</h3>

<p>整體來說，我認為這次的日本行可說是收獲滿滿，最大的遺憾是因為行程排的太緊加上八天兩場發表的關係，沒有好好的在松江當地觀光；希望明年可以作為普通的會眾參加這些活動。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RubyConf Taiwan 2015 ]]></title>
    <link href="http://ryudo.tw/blog/2015/09/20/rubyconftw-2015-retro/"/>
    <updated>2015-09-20T10:34:00+08:00</updated>
    <id>http://ryudo.tw/blog/2015/09/20/rubyconftw-2015-retro</id>
    <content type="html"><![CDATA[<p><img src="http://ryudo.tw/images/rubyconftw2015-og.png" alt="" /></p>

<p>今年是第五屆的 RubyConf Taiwan，也是第二次以總召的身份主辦這項活動。</p>

<h3>Matz Driven Development</h3>

<p>去年九月和龍哥帶著<a href="http://blog.annideas.com/2014/09/29/a-ruby-week-in-japan-1/">一群 Rails Girl 們</a>去參加 <a href="http://rubykaigi.org/2014">RubyKaigi 2014</a> ，在會前的某個特別 Party 上遇到 Matz，意外的被問到 2015 的 RubyConf Taiwan 何時舉辦，當時因為老婆的預產期在今年 2 月，所以就當場回覆可能無法在上半年舉辦，最後就和 Matz 敲定了大概會在今年的 9 月，所以我們是 Matz Driven Development 無誤。</p>

<h3>用公司推動 Conf</h3>

<p>剛好在去年的 RubyConf Taiwan 的前夕，考慮到未來的社群發展，和龍哥等人成立了 <a href="http://5xruby.tw">五倍紅寶石</a> 這間公司來推廣 Ruby，之後經過將近一年的努力經營之後，公司也漸漸開始有能力支援 <a href="http://5xruby.tw/posts/5xruby-support-sitcon">Sitcon</a> / Rails Girls Taipei / Weekly 和 Ruby Tuesday 等等，在這幾個月，可以說幾乎動用了整間公司的人力在舉辦這個活動。</p>

<p>以往在準備活動時，往往是以草創的心態去做，很多事情的聯繫或處理往往做的不到位或是有失誤的地方，今年要特別感謝敝公司的管理員 Sabrina ，帶領幾位同仁將大部份（對我來說）瑣碎的事務以最洗練的方式處理好，讓我幾乎不需要煩惱講者 / 贊助商 / 預算以外的事情，而且能適時的給我許多建議，讓我發現許多事情其實還可以做的比想像的更好。</p>

<h3>Matz is awseome, so we are awesome</h3>

<ul>
<li><p>補助外國講者住宿</p>

<p><img src="http://ryudo.tw/images/IMG_0587.jpg" alt="" /></p>

<p>來自 11 個不同國家的外國講者們，除了 Keynote Speaker 以外，全部都是自費來台，為了體貼遠道而來的外國講者們，今年特地補助外國講者免費住宿中研院的客房服務。</p></li>
</ul>


<blockquote class="instagram-media" data-instgrm-captioned data-instgrm-version="4" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div> <p style=" margin:8px 0 0 0; padding:0 4px;"> <a href="https://instagram.com/p/7cLiTZoF93/" style=" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;" target="_top">ホテルついたー。快適〜。</a></p> <p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;">A photo posted by igaiga (@igaiga555) on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2015-09-10T06:38:49+00:00">Sep 9, 2015 at 11:38pm PDT</time></p></div></blockquote>


<script async defer src="http://ryudo.tw//platform.instagram.com/en_US/embeds.js"></script>


<ul>
<li><p>使用 Icecast 做口譯接收解決方案</p>

<p>去年第一次嘗試在 Conf 做中翻英的即時口譯服務，當時因為場地因素，就找了專業的翻譯社架口譯間以及租借 Receiver；今年因為回到中研院，由於會場具備口譯間以及有 CPRTeam 支援網路的情況下，就決定使用之前 HITCON 使用的 Icecast 做口譯語音廣播的解決方案，讓外國會眾們用自己的手機接收口譯語音，得到了許多正面回應。</p></li>
</ul>


<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">&quot;Using Icecast instead of Receiver Equipment&quot;, that was a very nice idea! And that helped me so much. Thank you!! <a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a></p>&mdash; ゆかお(Yuka) (@yucao24hours) <a href="https://twitter.com/yucao24hours/status/642638603877793792">2015 9月 12日</a></blockquote>




<blockquote class="twitter-tweet" lang="zh-tw"><p lang="ja" dir="ltr">お手元のiPhoneにイヤホン差したら同時通訳レシーバーになるのとても便利だ <a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a></p>&mdash; Kakutani Shintaro (@kakutani) <a href="https://twitter.com/kakutani/status/642162711409750016">2015 9月 11日</a></blockquote>


<ul>
<li><p>Pre-Conf Party</p>

<p>由於經費與人力考量，以往 Conf 前通常沒有正式的活動，今年在 Conf 前兩天在敝礦坑舉辦 Pre-Conf Party，增加一個交流的機會。</p></li>
</ul>


<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">Beer and food! Pre-Conf party with so many <a href="https://twitter.com/hashtag/rubyfriends?src=hash">#rubyfriends</a> <a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a> <a href="http://t.co/jnR6pBf9FH">pic.twitter.com/jnR6pBf9FH</a></p>&mdash; Tina Huang (@tinating_h) <a href="https://twitter.com/tinating_h/status/641578793556033536">2015 9月 9日</a></blockquote>


<h3>場內</h3>

<ul>
<li><p>茶 / 咖啡贊助商</p>

<p>去年首次在活動中引進茶贊助商就有相當不錯的回應，後來也引發各大 Conf 爭相採用，今年剛好因為龍哥的關係認識了 iOS 大神張景隆夫妻經營的蘋果貓咖啡，另外剛好實習生的馨儀家裡又是經營茶莊的，就一次湊齊了兩種飲料攤位；連 Tenderlove 大神都表示他覺得這裡的咖啡比他住的西雅圖（星巴客發源地）的還要厲害，聽說連來自比利時的 @lrz 大神都帶了幾包回去。</p></li>
</ul>


<p><img src="http://ryudo.tw/images/2015-09-11%2010.33.41.jpg" alt="" /></p>

<ul>
<li><p>在會場交誼廳舉辦 Party</p>

<p>從 2012 起，我們就有在第一天晚上舉辦 Official Party 的傳統，前兩屆都在同一間 Lounge Bar 舉辦，雖然不用自己準備，但是需要一筆包場費用，也因此 Party 和 Conf 都要分開購票；今年直接使用會場四樓的交誼廳做為 Party 會場，從外面叫外燴，再配合 <a href="https://wish8.com">Wish8</a> 和 金色三麥贊助的啤酒，除了讓所有人都可以參加 Party 外，沒有座位的設定也讓大家比較容易主動交流。</p></li>
</ul>


<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">Start <a href="https://twitter.com/hashtag/RubyConfTW?src=hash">#RubyConfTW</a> <a href="http://t.co/uzQmocQTju">pic.twitter.com/uzQmocQTju</a></p>&mdash; 小影 ☂ (@siuying) <a href="https://twitter.com/siuying/status/642292642991075328">2015 9月 11日</a></blockquote>




<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">Beer time @ <a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a> <a href="http://t.co/MhnGcgg8Kp">pic.twitter.com/MhnGcgg8Kp</a></p>&mdash; 小影 ☂ (@siuying) <a href="https://twitter.com/siuying/status/642290286178123776">2015 9月 11日</a></blockquote>


<ul>
<li><p>RFID by Codeme.cc</p>

<p>以往贊助商擺攤，都需要自行收集會眾的資料，對於贊助商和會眾多有所不便之處，今年剛好透過龍哥認識了 PyCon 協辦單位之一的 GliaCloud，他們研發了一套 Raspberry Pi + RFID 打卡的解決方案，雙方討論之後就決定引進這個服務給贊助商使用，也感謝 Andy 和 Django Girl Taipei 的主辦人 Michelle 在場佈與兩天活動的全力支援，誰說不同語言 / 社群之間就不能通力合作呢？</p></li>
</ul>


<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">Badges linked with events <a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a> <a href="http://t.co/QtvAULcUPK">pic.twitter.com/QtvAULcUPK</a></p>&mdash; 小影 ☂ (@siuying) <a href="https://twitter.com/siuying/status/642288588722298885">2015 9月 11日</a></blockquote>


<p></p>

<h3>團隊</h3>

<ul>
<li>議程：ihower</li>
<li>設計：Rice / 康橋</li>
<li>顧問：龍哥</li>
<li>統籌：Sabrina</li>
<li>場地協調：Rock（OSSF）</li>
<li>攝影：徐聖淵</li>
<li>執行：Tina / 馨儀 / Nina</li>
<li>網站：Nina / 西瓜 / Tina / 蒼時</li>
<li>口譯：Sarah / 宜靜</li>
<li>司儀：Lillian / 郁蓁</li>
<li>場務：Tina / 馨儀 / Nina / 雯晴 / 嘉佑 / Christine / okay / 椽家 / 孟穎 / 宇辰 / 芳妤 / 毓柔 / 佾庭 / 詩晴</li>
<li>會場網路：Mouse / Pennyyken（CPR Team）</li>
<li>RFID：Andy / Michelle（Gliacloud）</li>
<li>外交大使：@juanitofatas</li>
</ul>


<h3>結語</h3>

<p>感謝贊助商 / 協力夥伴 / Staff / 講者以及許多朋友的幫忙才能促成今年的活動順利舉辦，謝謝大家！</p>

<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr">All <a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a> staffs with <a href="https://twitter.com/tenderlove">@tenderlove</a> &#39;s cat sticker <a href="http://t.co/vtKYiGRnHs">pic.twitter.com/vtKYiGRnHs</a></p>&mdash; Mu-Fan Teng (@ryudoawaru) <a href="https://twitter.com/ryudoawaru/status/642683230055825413">2015 9月 12日</a></blockquote>




<blockquote class="twitter-tweet" lang="zh-tw"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/rubyconftw?src=hash">#rubyconftw</a> Staffs and <a href="https://twitter.com/masterwujiang">@masterwujiang</a> after party. <a href="http://t.co/mqbOBr3kjy">pic.twitter.com/mqbOBr3kjy</a></p>&mdash; Ruby Taiwan (@rubytaiwan) <a href="https://twitter.com/rubytaiwan/status/642353458939478016">2015 9月 11日</a></blockquote>


<p> <script async src="http://ryudo.tw//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[解決用 Mac 登入 Linux 主機時出現的 locale 警告訊息]]></title>
    <link href="http://ryudo.tw/blog/2015/02/20/fix-locale-in-linux/"/>
    <updated>2015-02-20T16:07:00+08:00</updated>
    <id>http://ryudo.tw/blog/2015/02/20/fix-locale-in-linux</id>
    <content type="html"><![CDATA[<p>前陣子用 Mac 登入遠端的 Linux 主機時常常遇到一個有點討厭的訊息：</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='bash'><span class='line'>-bash: warning: setlocale: LC_CTYPE: cannot change locale <span class="o">(</span>UTF-8<span class="o">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>這個狀況是從幾個月前突然發生的，Google 之後發現兩種解法：</p>

<ol>
<li><p>修改主機 locale 設定</p>

<p>編輯：/etc/environment 或是 .bash_xxx 等檔案並輸入：
<code>
LANG=en_US.utf-8
LC_ALL=en_US.utf-8
</code></p></li>
<li><p>修改 iterm 設定</p></li>
</ol>


<p><img src="http://ryudo.tw/images/iterm-local-setting.jpg" alt="" /></p>

<p>將裡面的 &#8220;Set locale variables automatically&#8221; 取消勾選即可。</p>

<h3>相關連結</h3>

<ul>
<li>https://sskaje.me/2014/01/lc-ctype-issue/#.VOwSjULdVRE</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[自動化測試 Rails 中的 URL HELPER]]></title>
    <link href="http://ryudo.tw/blog/2015/02/18/automatic-urlhelper-test-in-rails/"/>
    <updated>2015-02-18T12:51:00+08:00</updated>
    <id>http://ryudo.tw/blog/2015/02/18/automatic-urlhelper-test-in-rails</id>
    <content type="html"><![CDATA[<h3>前言：</h3>

<p>最近在某個和客戶共同開發的專案中，遇到了以下的情形：</p>

<ol>
<li>專案的 layout / view 經過大幅的改版</li>
<li>改版是把舊 layout（以下簡稱 ver1）的大部份功能改出一份新版 layout / view / controller（以下稱 ver2）</li>
<li>改版後幾乎沒有移除 ver1 重複的部份，因此系統中存著很多其實用不到的 view / controller / route</li>
<li>又因為改版後不想改變在 production env 的 url，所以在路由設定中用了大概是類似的架構：

<ul>
<li>Development 中有 /ver1 和 /ver2 兩個 route namespace，而且有 base uri，意即可能會有 /ver1/products 和 /ver2/products</li>
<li>Production 中，這兩個 namespace 的 base uri 會被消除，舉例來說，如果遇到 /products 的 request，系統會先找 /ver2 有沒有 /products，有的話會先使用，沒有再去找 /ver1</li>
</ul>
</li>
</ol>


<p>所以系統最後就存在一堆功能重疊的 controller / view / layout 了，現在的工作是要移除 /ver1 和 /ver2 中重複的部份。</p>

<h3>執行：</h3>

<p>基本上就是高科技手工業，程序如下：</p>

<ol>
<li>找 /ver2 的 route，假設現在的目標是 resources :users</li>
<li>在 /ver1 上找尋類似的 resource</li>
<li>如果有，就把 /ver1 的刪掉</li>
<li>如果不是單純的 Restful CRUD（意指有其它非 index. show, create 等標準 action 的 action）就得要一一檢查在 /ver2 上是否都有相對應的 action</li>
<li>找到所有的 view / helper / asset / controller 中是否有用到 /ver1 上的 url helper method，然後統一取代</li>
</ol>


<p>以上程序有效的前提是，所有的 URL 都用 helper method 而不用純字串或 url_for 等。</p>

<p>事情聽起來好像不是很難，不過這個專案可怕的地方就在於數百行的 route 中幾乎沒有單純 CRUD 的 resource，所以和同事花上了很多時間在手工上，完成後的問題就是，要怎樣確保沒有遺漏的地方。</p>

<p>於是想到，是否可以將程式中所有用到的 url helper method 集合起來一一做檢查呢？最後想到的解法大意如下：</p>

<ol>
<li>用文字搜尋的程式，以正規表示式去找出程式碼中使用的 url helper method</li>
<li>將找到的 method 集合產生列表</li>
<li>用列表產生 it 區塊</li>
<li>it 區塊中使用 <a href="https://www.relishapp.com/rspec/rspec-rails/v/2-4/docs/helper-specs/helper-spec">helper spec</a> 去測試 view context 中是否有這些 method</li>
</ol>


<p>文字搜尋採用目前比較流行的 <a href="http://beyondgrep.com/">ack</a>，好處是除了速度快之外又是 Perl 版的 Regexp，比 egrep 內建的更貼近 Ruby 使用的版本</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='bash'><span class='line'>ack --noheading -h <span class="s1">&#39;[^A-Za-z0-9_.].((ver1|ver2)[\\w_]+?\_(url|path))&#39;</span> app/ --output <span class="s1">&#39;$1&#39;</span> | sort | uniq
</span></code></pre></td></tr></table></div></figure>


<p>使用的 ack 參數如下：</p>

<ul>
<li>正規表示式為：<code>[^A-Za-z0-9_.].((ver1|ver2)[\\w_]+?\_(url|path))</code></li>
<li>&#8211;noheading 不顯示檔案名在頭</li>
<li>-h 不顯示檔名在左邊</li>
<li>&#8211;output &#8216;$1&#8217; 只顯示批配的第 1 項</li>
</ul>


<p>測試的程式大概長的像這樣：</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="no">RSpec</span><span class="o">.</span><span class="n">describe</span> <span class="no">ApplicationHelper</span><span class="p">,</span> <span class="ss">:type</span> <span class="o">=&gt;</span> <span class="ss">:helper</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">fn</span> <span class="o">=</span> <span class="s2">&quot;tmp/url_helpers.txt&quot;</span>
</span><span class='line'>  <span class="n">cmd</span> <span class="o">=</span> <span class="s2">&quot;ack --noheading -h &#39;[^A-Za-z0-9_.].((ver1|ver2)[</span><span class="se">\\</span><span class="s2">w_]+?\_(url|path))&#39; app/ --output &#39;$1&#39; | sort | uniq &gt; </span><span class="si">#{</span><span class="n">fn</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'>  <span class="nb">system</span> <span class="n">cmd</span>
</span><span class='line'>  <span class="no">File</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">url_helper_name</span><span class="o">|</span>
</span><span class='line'>    <span class="n">it</span> <span class="s2">&quot;Url helper </span><span class="si">#{</span><span class="n">url_helper_name</span><span class="si">}</span><span class="s2"> should be available&quot;</span> <span class="k">do</span>
</span><span class='line'>      <span class="n">helper</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="n">url_helper_name</span><span class="o">.</span><span class="n">to_sym</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="n">be</span><span class="p">(</span><span class="kp">true</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>這樣一跑完就可以放心了。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在 Mac / Homebrew 下升級 PostgreSQL 從 9.3 到 9.4]]></title>
    <link href="http://ryudo.tw/blog/2015/02/15/upgrade-pgsql-from-93-to-94/"/>
    <updated>2015-02-15T22:10:00+08:00</updated>
    <id>http://ryudo.tw/blog/2015/02/15/upgrade-pgsql-from-93-to-94</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<p>PostgreSQL 和 MySQL 不同，資料檔格式會隨著小數點二位數以上的版號（9.3 - 9.4）變動，換句話說每當升級版本時，資料檔就必需要升級才可以繼續使用。</p>

<p>升級的方式有兩種：</p>

<ul>
<li>將原本的資料執行 <a href="http://www.postgresql.org/docs/9.4/static/app-pg-dumpall.html">pg_dumpall</a> 後再 restore 回去</li>
<li>用 <a href="http://www.postgresql.org/docs/9.4/static/pgupgrade.html">pg_upgrade</a> 命令從舊的資料檔產生出新版本的資料檔。</li>
</ul>


<p>這邊要講的是第二種情形。</p>

<h3>環境限定：</h3>

<ul>
<li>可執行 <a href="http://brew.sh/">Homebrew</a> 的 MacOS 環境</li>
<li>原 PostgreSQL 為 Homebrew 安裝，9.3.x 版</li>
</ul>


<h3>步驟</h3>

<ol>
<li>安裝新的 PostgreSQL

<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='bash'><span class='line'>brew update
</span><span class='line'>brew install postgresql
</span></code></pre></td></tr></table></div></figure>

</li>
<li>停止現在的 PostgreSQL Daemon
<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='bash'><span class='line'>launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
</span></code></pre></td></tr></table></div></figure>
</li>
<li>建立 9.4 的資料庫檔案
<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='bash'><span class='line'>initdb /usr/local/var/postgres9.4 -E utf8
</span></code></pre></td></tr></table></div></figure>
</li>
<li>使用 pg_upgrade 指令升級 舊PG的資料檔案到 9.4，注意這邊的 9.3.5_1 和 9.4.0 是會依照你的舊版本和實際安裝的新板本的版號而有差異的

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>pg_upgrade -v <span class="se">\</span>
</span><span class='line'>    -d /usr/local/var/postgres <span class="se">\</span>
</span><span class='line'>    -D /usr/local/var/postgres9.4 <span class="se">\</span>
</span><span class='line'>    -b /usr/local/Cellar/postgresql/9.3.5_1/bin/ <span class="se">\</span>
</span><span class='line'>    -B /usr/local/Cellar/postgresql/9.4.0/bin/
</span></code></pre></td></tr></table></div></figure>
</li>
<li>將舊資料檔備份，並且讓新資料檔的目錄更名使之變成預設的資料檔

<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='bash'><span class='line'><span class="nb">cd</span> /usr/local/var
</span><span class='line'>mv postgres postgres9.3
</span><span class='line'>mv postgres9.4 postgres
</span></code></pre></td></tr></table></div></figure>
</li>
<li>
重啟 PostgreSQL

<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='bash'><span class='line'>launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
</span></code></pre></td></tr></table></div></figure>
</li>

<li>檢查 /usr/local/var/postgres/server.log 檔是否有正常啟動 server</li>
<li>如果原本有安裝
<a href="https://rubygems.org/gems/pg">pg GEM</a>
的話要重新安裝</li>
</ol>


<p>以上！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[銘謝文--RubyKaigi 2014之旅以及 Rails Girls Taipei 獎助金計劃]]></title>
    <link href="http://ryudo.tw/blog/2014/09/28/shibuya-it-tour-by-igaiga555/"/>
    <updated>2014-09-28T22:00:00+08:00</updated>
    <id>http://ryudo.tw/blog/2014/09/28/shibuya-it-tour-by-igaiga555</id>
    <content type="html"><![CDATA[<h3>緣起</h3>

<p>由於有了去年第一次和高見龍等人一同參加 <a href="http://ryudo.tw/blog/2013/06/07/rubykaigi2013-lt/">RubyKaigi 2013</a> 的經驗，因此當確定今年的 RubyKaigi時程後，就非常的期待有機會能夠再次參加這場 Ruby世界最重要的研討會。</p>

<p>今年的 RubyConf.tw 2014 ，做為總召，有幸召集到了許多 Rails Girls Taipei 活動的校友們做為志工一起舉辦了這場國際研討會。</p>

<p>會中主要贊助商之一的 Heroku 的代表，也是 Ruby Committer 的相澤步先生提及，或許可以嘗試由 Heroku 公司和日本的社群朋友贊助一些台灣的 RG 校友去日本參加 Ruby Kaigi 2014，當時覺得這個點子非常棒，但又覺得有點不現實。</p>

<p>在七月籌備 RG Taipei-4 時，透過 E-Mail 向相澤先生詢問此事之後，得到了肯定的回覆，於是就著手開始<a href="http://railsgirls.tw/2014/07/28/rubykaigi-scholarship/">選拔辦法</a>。</p>

<p>在選拔過程中，也用英文向日方提交了每位報名者的近況，包含社群參與度等等的報告，最後在八月和日方一起開會共同決定了三位入選者，神奇的是過程中，本來以為只有 Heroku 公司會出錢，沒想到後來加入了 Spice Life 公司以及好幾位日本的大大，其中有幾位是甚至沒有來過台灣，單純的被 RG 的理念感召，實在是令人非常感動。</p>

<p>另一方面，在規劃這次的日本行之時，就想到是否有機會可以參觀一些日本的 IT 系企業，於是就聯絡了之前認識的日本 Ruby 圈的大大們，才有幸在日本行中參觀到包括 Line / DeNA 等等的 IT 企業們。</p>

<h3>成員</h3>

<p><img src="https://farm6.staticflickr.com/5573/15081062158_baa41b8641_b_d.jpg" alt="" />
Photo by Igarashi Kuniaki</p>

<ol>
<li>龍哥</li>
<li>大兜（講者）</li>
<li>Bruce（講者）</li>
<li>Mason</li>
<li>Annie（RG 獎助金計劃獲選者）</li>
<li>阿旺（RG 獎助金計劃獲選者）</li>
<li>Lena（RG 獎助金計劃獲選者）</li>
</ol>


<h3>參加了哪些活動</h3>

<p>可參考下列文章與分享：</p>

<ul>
<li><a href="http://blog.annideas.com/2014/09/29/a-ruby-week-in-japan-1/">A ruby week in Japan (1) by Annie </a></li>
<li><a href="https://awonwon.wordpress.com/2014/10/05/rubykaigi-%E6%9D%B1%E4%BA%AC%E4%B8%80%E9%80%B1%E9%81%8A-1/">RubyKaigi 東京一週遊 (1) by 阿旺</a></li>
<li><a href="http://railsgirls.kktix.cc/events/rubykaigi2014">特別講座：Rails Girls vs. RubyKaigi</a> 的 Slide by Annie</li>
</ul>


<center><iframe src="http://ryudo.tw//www.slideshare.net/slideshow/embed_code/43105512?startSlide=10" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="http://ryudo.tw//www.slideshare.net/AnnieChen51/rubykaigi-43105512" title="鐵道女孩向前衝-RubyKaigi心得分享" target="_blank">鐵道女孩向前衝-RubyKaigi心得分享</a> </strong> from <strong><a href="http://ryudo.tw//www.slideshare.net/AnnieChen51" target="_blank">Annie Chen</a></strong> </div></center>


<ul>
<li>同上的影片紀錄</li>
</ul>


<center><iframe width="853" height="480" src="https://www.youtube.com/embed/ggdH2VTqZ_U" frameborder="0" allowfullscreen></iframe></center>


<h3>結語</h3>

<p>一年多前參加 RubyKaigi 2013 並參觀到日本的 RG 活動時，沒想過在台灣可以辦的起來 RG ，更沒想過有機會參與到史無前例的獎助金計劃，只能說 Ruby 社群的力量真的太神奇了！</p>

<h3>特別感謝</h3>

<ul>
<li>Heroku, Inc</li>
<li>株式会社spice life</li>
<li>Heroku 的 相澤 步（Ayumu Aizawa） 先生</li>
<li>Spice Life 的 五十嵐 邦明（Kuniaki Igarashi） 先生</li>
<li>Satoshi Gunji 先生</li>
<li>Hiroshi Shibata 先生</li>
<li>松田 明 （Akira Matsuda）先生</li>
<li>Haruka Iwao 小姐</li>
<li>Chiaki Shinto 小姐</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RubyConf Taiwan 2014]]></title>
    <link href="http://ryudo.tw/blog/2014/07/04/rubyconftw2014-recap/"/>
    <updated>2014-07-04T14:39:00+08:00</updated>
    <id>http://ryudo.tw/blog/2014/07/04/rubyconftw2014-recap</id>
    <content type="html"><![CDATA[<p>按照往年的慣例，這篇也拖稿了超級久。</p>

<h3>時間和場地</h3>

<p>記得應該是 2013 的 11月左右，和 Matz 確認日期後開始找場地。</p>

<p>本來一開始是想用中研院的，不過和 2012 一樣，Matz 欽訂的日期又沒空了，正在煩惱場地時想到離（當時）工作地點很近的陽明大學，剛好社群的好朋友澤清當時也還在那邊工作，於是在想到的當天就立刻去看場地，由於和澤清所屬單位（陽明大學系合中心）合辦的話可以獲得場地租金的優惠，加上場地狀況整體不差，於是當下就拍板定案，於是和 2012 一樣，又辦在了中研院以外的地方，而且一樣在台北北區。</p>

<p>交通方面，由於是在石牌捷運站步行 10 分鐘的地點，因此沒有造成任何不便。</p>

<p>這次場地的優點：</p>

<ol>
<li>夠大</li>
<li>兩個場地後面是相通的</li>
<li>很多廳</li>
</ol>


<p>缺點：</p>

<ol>
<li>休息區的位子較少</li>
<li>大禮堂和其它廳的人數差距太大（1000 : 240）不過由於我們只有 290 左右的會眾，因此不是問題</li>
</ol>


<p><img src="https://farm8.staticflickr.com/7343/13949888418_1a56859133_b_d.jpg" alt="" />
<img src="https://farm3.staticflickr.com/2905/14156661363_fc3c682696_b_d.jpg" alt="" /></p>

<h3>Linda Liukas</h3>

<p><img src="https://farm8.staticflickr.com/7357/13955615790_e9b397b6a2_b_d.jpg" alt="" /></p>

<p>有鑑於 Rails Girls 在全球各地的蓬勃發展，就決定邀請 Linda 做為本次大會的 Keynote Speaker 之一，雖然一開始會擔心非技術議題大家是否會感興趣，不過看場下大家爭相和她合照的情形也就放心了，果然不愧是 Ruby 界的女神！</p>

<p>其實有趣的是 2014 的 RubyKaigi 也有 RG 相關的<a href="http://rubykaigi.org/2014/presentation/S-HarukaIwao">議程</a>，看來這應該是趨勢無誤。</p>

<h3>設計</h3>

<p><img src="http://rubyconf.tw/2014/img/logo800.png" alt="" />
<img src="https://farm3.staticflickr.com/2923/13949856908_bfa1778e2d_b_d.jpg" alt="" /></p>

<p>這次的官網 / APP，包括所有看得到的平面設計，都是由 RG 出身的 Grace 擔任，和以往相比多出了很多的平面設計物，由於她有許多展場設計的經驗，所以我可以放心的將細節交給她。</p>

<h3>Mobile APP</h3>

<p>在一個不是以 APP 為主題的 conf 推出了雙平台的 APP，要感謝擔任 iOS 開發的<a href="http://blog.eddie.com.tw">龍哥</a>以及幾位 <a href="https://www.alphacamp.co">Alphacamp</a> 的學員，還有擔任 Android 開發的阿旺以及協助她的佳緯。</p>

<h3>CFP &amp; 講者</h3>

<p>這次的 <a href="http://rubyconftw-agenda.kktix.cc/events/rubyconftw2014-cfp">CFP</a> 讓我最意外的是，在沒有招待食宿機票的狀況下，投稿者裡面竟然有超過一半的外國投稿，有鑑於此，後來也開放了讓這些講者的所屬單位掛上了特別的 Speaker Sponsorship 作為一種回饋。</p>

<p>講者（包括 Keynote）來自於包括台灣在內有七個不同的國家，分佈為：</p>

<ol>
<li>台灣：10</li>
<li>日本：8</li>
<li>美國：7</li>
<li>香港：1</li>
<li>中國：1</li>
<li>芬蘭：1</li>
<li>比利時：1</li>
<li>新加坡：1</li>
</ol>


<p>另一個和以往差異較大的，就是出現了高達 4 位的女性講者，如果加上了 LT 的話就有 5 位了，這也算是某種程度的突破吧。</p>

<h3>食物 &amp; 飲料</h3>

<p>抱歉第一天搞砸了，還好第二天的便當大家還算滿意。</p>

<p>飲料方面，第一次引進了飲料贊助商琅茶，這間也是由幾位前趨勢和 HTC 的工程師創業成立的，現場看起來大家很捧場，後來聽說不少外國會眾都訂了茶葉帶回去。</p>

<p><img src="https://farm8.staticflickr.com/7426/14113451476_bdd06c8c4c_b_d.jpg" alt="" /></p>

<h3>Party</h3>

<p>和 2012 選擇了相同的場地舉辦了 Party，不過這次我們可是把整間都給包下來了，又加入了台灣和日本的 Rails Girls ，整個場面好不熱鬧。</p>

<p><img src="https://farm8.staticflickr.com/7304/14138851711_80083ac273_b_d.jpg" alt="" />
<img src="https://farm8.staticflickr.com/7436/14161770203_dab23d06dd_b_d.jpg" alt="" /></p>

<h3>語言與國際化</h3>

<p><img src="https://farm3.staticflickr.com/2925/14133536472_9fe6e4dbdf_b_d.jpg" alt="" /></p>

<p>繼承本大會的傳統，這次的會眾中有將近 1/4 來自超過 10 個不同國家。</p>

<p>受到去年 RubyKaigi 2013 的啟發，為了促進國內外會眾的交流，這次特別啟用了中翻英即時口譯在所有的中文議程上，也因此把所有的中文議程都排在了第一天。</p>

<p>為了節省經費而不找口譯公司，從 ptt 口譯版上募集到了兩位超優秀的口譯 Sarah 和 Kylie，她們除了專業能力和資歷外，重要的是對整個活動的負責態度，像是在活動前一個月場勘，或是主動聯繫講者溝通演講內容等，讓我覺得能請到她們真的非常幸運。</p>

<h3>Rails Girls 特別講座</h3>

<p><img src="https://farm8.staticflickr.com/7392/13979240477_0816537871_b_d.jpg" alt="" /></p>

<p>原本在 conf 的隔日，打算按照日本的 <a href="http://rubykaigi.doorkeeper.jp/events/3509">RubyHiroba</a> 的方式，舉辦一個 <a href="http://en.wikipedia.org/wiki/Unconference">Unconference</a> 的活動並且混合 RG，不過在和出身於 RG 的 <a href="https://hazelwei.wordpress.com/about-miss-hazel/">Hazel</a> 討論後，決定趁著這次邀請到 Linda（Rails Girls Co-Founder） 的機會來舉辦一場特別的座談會活動，也因此促成了「<a href="http://www.accupass.com/go/rgtalk427">姺語言力-程式新市場，女孩新火花</a>」的舉辦。</p>

<p>一開始邀請的講者是國內的大神唐鳳和 Linda，活動進行中加入了原本在台下當聽眾的 Matz 和 @headius，讓整個座談變得更加精采。</p>

<iframe width="853" height="480" src="https://www.youtube.com/embed/videoseries?list=PLfrYA2oGCwQWldZdfKDVJUGg5KcYMdYxR" frameborder="0" allowfullscreen></iframe>


<p>在這裡必需特別推崇 Hazel，在整個講座的籌備過程中，她持續的和 Linda  以及唐鳳討論座談的細節，另外也要感謝這次的場務組長包子幫忙聯繫媒體等事宜，另外也要感謝 TEDxTaipei 贊助了活動場地，以及 Lena 贊助了活動 LOGO 的設計。</p>

<p>同時也要感謝 Inside 的編輯，也是 RG 校友的 Liz 對 Linda 進行的<a href="http://www.inside.com.tw/2014/07/30/rails-girls-founder-linda-liukas-interview">深度採訪</a>，還有贊助拍攝的 <a href="https://www.facebook.com/RETINA.STUDIO.TAIWAN">Retina Studio</a></p>

<h3>Rails Girls Staffs</h3>

<p>自從 2013 的 9 月開始舉辦第一次的 Rails Girls Taipei 之後，就認識了許多優秀的 Rails Girls 們，加上受到去年在日本看到很多 RubyKaigi 的 staff 都是女性工程師等的啟發，覺得應該可以試著在 RG 中招募 staff 看看，結果報名者超乎想像的多，最後幾乎所有的會場 staff 都是來自 RG 校友。</p>

<p><img src="https://farm8.staticflickr.com/7314/14136726064_ca92cb8b49_b_d.jpg" alt="" />
<img src="https://farm8.staticflickr.com/7453/14133537102_8f7a63291b_b_d.jpg" alt="" /></p>

<p>同時這個亮點也引起了在場許多外國朋友的注意，也進而造就了日後的 <a href="http://railsgirls.tw/2014/07/28/rubykaigi-scholarship/">RubyKaigi 獎助金計劃</a>。</p>

<p>個人以為，RG Staff 對 Ruby  社群的最大意義並不是因為她們是正妹或女生，而是讓受惠於社群學習到 Ruby 的校友們有一個產生正向循環並回饋社群的機會。</p>

<h3>總結</h3>

<p>感謝 ihower 給我擔任總召的機會，也由於有幸參加 RubyKaigi 2013 受到了許多啟發，把 RubyConf Taiwan 的特色延續下去並成功的辦出一屆國際化又有特色的程式語言研討會，謝謝大家！</p>

<h3>Next Time？</h3>

<p>預計於 2015.09，敬請期待！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[PostgreSQL Materialized View簡介]]></title>
    <link href="http://ryudo.tw/blog/2014/06/20/use-materizlied-view-in-pgsql/"/>
    <updated>2014-06-20T15:54:00+08:00</updated>
    <id>http://ryudo.tw/blog/2014/06/20/use-materizlied-view-in-pgsql</id>
    <content type="html"><![CDATA[<p>最近在開發某個主力產品時遇到了一個問題，就是當我們在後台編輯一些資料，包含新增 / 修改 / 刪除
，然後在沒有完成所有編輯前不想讓修改中的資料立刻在前台生效，正在苦思如何完成這項功能時，發現了PostgreSQL有一個超好用的功能叫「Materialized View」，於是就開始survey看看。</p>

<h2>Database View</h2>

<p>在<a href="http://en.wikipedia.org/wiki/View_%28SQL%29">Wikipedia</a>中的說明為：</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'>檢視表 (View) 是在關聯式資料庫中，將一組查詢指令構成的結果集，在實體資料表中的改變都可以立刻反應在檢視表中</span></code></pre></td></tr></table></div></figure>


<p>通常我們會為了特定目的，例如將某些特定條件的查詢變成一張虛擬表之類的原因，來製作一些View，例如：</p>

<p><img src="http://ryudo.tw/assets/2014/06/20/use-materizlied-view-in-pgsql/ex-order-erd.png"></p>

<p>我們會用以下的方式建立一個View：</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='sql'><span class='line'><span class="k">CREATE</span> <span class="k">VIEW</span> <span class="n">orders_products_users</span> <span class="k">AS</span>
</span><span class='line'><span class="k">SELECT</span>
</span><span class='line'><span class="n">orders</span><span class="p">.</span><span class="n">user_id</span><span class="p">,</span>
</span><span class='line'><span class="n">users</span><span class="p">.</span><span class="n">name</span><span class="p">,</span>
</span><span class='line'><span class="n">orders</span><span class="p">.</span><span class="n">product_id</span><span class="p">,</span>
</span><span class='line'><span class="n">products</span><span class="p">.</span><span class="n">name</span>
</span><span class='line'><span class="k">FROM</span>
</span><span class='line'><span class="n">orders</span> <span class="k">JOIN</span> <span class="n">users</span> <span class="k">ON</span> <span class="n">users</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">orders</span><span class="p">.</span><span class="n">user_id</span><span class="p">,</span>
</span><span class='line'><span class="k">JOIN</span> <span class="n">products</span> <span class="k">ON</span> <span class="n">products</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">orders</span><span class="p">.</span><span class="n">product_id</span>
</span></code></pre></td></tr></table></div></figure>


<p>以後我們要使用這個view時只要：</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='sql'><span class='line'><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">orders_products_users</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>即可</p>

<p>但是普通的view本身並沒有真正的儲存資料，預設情況下它只是一個查詢的捷徑而已，而且也不能透過update view來更新資料，所以對於使用Rails等ORM的人來說，即使已經有一些「把view當model」的Gem（例如<a href="https://github.com/stevo/activerecord-database-views">activerecord-database-views</a>）推出，還是會覺得是一個比較雞肋的功能。</p>

<h2>Materialized View（以下簡稱M-View）</h2>

<p>今天要介紹的這個功能和普通的View的差別，就在建立出來的view是一個查詢狀態的「快照」（Snapshot），在快照建立後，只要不更新（Refresh），即使對原本的table有任何的變更，這個M-View裡的資料也不會有任何變化，因此就可以做到前面所說的，讓後台更新的資料不影響到前台的功能，接下來讓我們來看看如何使用這個功能。</p>

<h2>Postgresql的Materialized View</h2>

<p>這個功能原本是出自於Oracle，號稱「開源的Oracle」的PostgreSQL也在本文撰時最新的穩定版本9.3加入了該功能，<a href="http://www.postgresql.org/docs/9.3/static/sql-creatematerializedview.html">參考資料</a>。</p>

<h3>建立Materialized View</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>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sql'><span class='line'><span class="k">CREATE</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span> <span class="k">table_name</span>
</span><span class='line'>    <span class="k">AS</span> <span class="n">query</span>
</span><span class='line'>    <span class="p">[</span> <span class="k">WITH</span> <span class="p">[</span> <span class="k">NO</span> <span class="p">]</span> <span class="k">DATA</span> <span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>例如：</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='sql'><span class='line'><span class="k">CREATE</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span> <span class="n">mymatview</span> <span class="k">AS</span> <span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">mytab</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>以上指令會以「SELECT * FROM mytab」的查詢式建立一個名為「mymatview」的M-View，而且在refresh之前，mymatview的內容不會受到原本mytab更新的影響。</p>

<p>結尾的WITH DATA 和 WITH NO DATA的差別是在，會不會在建立時就把當時的資料填進去，如果WITH NO DATA的話，就必需要再使用refresh才可以把資料填進去。</p>

<h3>更新Materialized View</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='sql'><span class='line'><span class="n">REFRESH</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span>  <span class="n">M</span><span class="o">-</span><span class="k">View</span><span class="err">的名稱</span>
</span></code></pre></td></tr></table></div></figure>


<p>一旦下了這個指令後，就可以將現在的資料內容更新到指定的M-View上</p>

<h3>移除Materialized View</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='sql'><span class='line'><span class="k">DROP</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span>  <span class="n">M</span><span class="o">-</span><span class="k">View</span><span class="err">的名稱</span> <span class="p">[</span><span class="k">CASCADE</span> <span class="o">|</span> <span class="k">RESTRICT</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>顧名思義，即完全移除該M-View，CASCADE意即在移除此物件實「一併移除相關物件」。</p>

<h3>Materialized View的注意事項</h3>

<ol>
<li>和普通View一樣，不可以用UPDATE或INSERT等更新內容</li>
<li>如果建立了M-View後，要移除關聯的資料表時需要用CASADE方式一併移除相關M-View，否則會無法移除。</li>
<li>可以多層重疊，意即可以透過「查詢M-View建立其它M-View」</li>
</ol>


<h2>Materialized View的用途</h2>

<ol>
<li>加速部份查詢
和一般View不同，M-View佔有獨立表空間，所以查詢M-View不會影響到關聯的資料表，意即如果我們將一些複雜或費時的查詢的結果用M-View建立快照的話，可以透過查詢該M-View節省下一次查詢的時間，例如某個交易資料表如果有10年份1000萬筆的話，將某一年份的交易資料獨立查詢到一個M-View之後，要查詢該年份的交易資料只要查詢該M-View，就不需要在查詢中scan全部10年份的交易資料了。</li>
<li>實現資料版本控制
這是我原本想要使用的目的，這個功能可以玩的地方還很多，例如我們</li>
</ol>


<h2>範例</h2>

<p>今天假設有如下的表</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='sql'><span class='line'><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">spree_products</span>
</span><span class='line'><span class="p">(</span>
</span><span class='line'>  <span class="n">id</span> <span class="nb">serial</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
</span><span class='line'>  <span class="n">name</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span> <span class="k">NOT</span> <span class="k">NULL</span> <span class="k">DEFAULT</span> <span class="s1">&#39;&#39;</span><span class="p">::</span><span class="nb">character</span> <span class="nb">varying</span><span class="p">,</span>
</span><span class='line'>  <span class="n">description</span> <span class="nb">text</span><span class="p">,</span>
</span><span class='line'>  <span class="n">available_on</span> <span class="k">timestamp</span> <span class="k">without</span> <span class="n">time</span> <span class="k">zone</span><span class="p">,</span>
</span><span class='line'>  <span class="n">deleted_at</span> <span class="k">timestamp</span> <span class="k">without</span> <span class="n">time</span> <span class="k">zone</span><span class="p">,</span>
</span><span class='line'>  <span class="n">slug</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">255</span><span class="p">),</span>
</span><span class='line'>  <span class="n">meta_description</span> <span class="nb">text</span><span class="p">,</span>
</span><span class='line'>  <span class="n">meta_keywords</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">255</span><span class="p">),</span>
</span><span class='line'>  <span class="n">tax_category_id</span> <span class="nb">integer</span><span class="p">,</span>
</span><span class='line'>  <span class="n">shipping_category_id</span> <span class="nb">integer</span><span class="p">,</span>
</span><span class='line'>  <span class="n">created_at</span> <span class="k">timestamp</span> <span class="k">without</span> <span class="n">time</span> <span class="k">zone</span><span class="p">,</span>
</span><span class='line'>  <span class="n">updated_at</span> <span class="k">timestamp</span> <span class="k">without</span> <span class="n">time</span> <span class="k">zone</span><span class="p">,</span>
</span><span class='line'>  <span class="k">CONSTRAINT</span> <span class="n">spree_products_pkey</span> <span class="k">PRIMARY</span> <span class="k">KEY</span> <span class="p">(</span><span class="n">id</span><span class="p">)</span>
</span><span class='line'><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>然後我們建立如下的M-View</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='sql'><span class='line'><span class="k">CREATE</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span> <span class="n">spree_products_mview</span> <span class="k">AS</span>
</span><span class='line'> <span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">spree_products</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>然後我們看現在的 spree_products表內容如下：
<img src="http://ryudo.tw/assets/2014/06/20/use-materizlied-view-in-pgsql/mview-original.png" alt="" />
此時table和M-View的資料應該是一致的，此時我們將資料表的一些資料刪除：</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='sql'><span class='line'><span class="k">DELETE</span> <span class="k">FROM</span> <span class="n">spree_products</span> <span class="k">WHERE</span> <span class="n">id</span> <span class="o">=</span> <span class="mi">16</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>此時id為16的紀錄已經被移除
<img src="http://ryudo.tw/assets/2014/06/20/use-materizlied-view-in-pgsql/after-remove.png" alt="" />
但是M-View的資料還是一樣的，如下圖
<img src="http://ryudo.tw/assets/2014/06/20/use-materizlied-view-in-pgsql/mview-after-remove.png" alt="" />
這時如果我們下了REFRESH的話：</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='sql'><span class='line'><span class="n">REFRESH</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span> <span class="n">spree_products_mview</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>M-View的資料就會和資料表上一樣了</p>

<p>以上是簡介Materizlied View在PostgreSQL的作用，接下來我們還會針對如何用Rails / ActiveRecord操作這個功能作出說明。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[2013回顧[CH]]]></title>
    <link href="http://ryudo.tw/blog/2014/01/01/my2013/"/>
    <updated>2014-01-01T00:18:00+08:00</updated>
    <id>http://ryudo.tw/blog/2014/01/01/my2013</id>
    <content type="html"><![CDATA[<h2>2013大事紀</h2>

<ul>
<li> 一月, 在WebConf Taiwan 2013 發表「<a href="http://www.youtube.com/watch?v=WEgoBZkS9Uw">非典型貧窮網站維運經驗分享</a>」</li>
<li>二月, 舉辦[Ruby 20週年慶祝趴] (https://kktix.com/events/ruby20)</li>
<li>四月, 接棒ihower主辦Ruby Tuesday以及<a href="http://ruby.tw">Ruby Taiwan社群</a>, 開始<a href="https://kktix.com/events/ruby-tuesday-22/">Ruby Tuesday 22</a></li>
<li>五月底, 和社群朋友一同參加<a href="http://rubykaigi.org/2013/">Ruby Kaigi 2013</a>, 並發表<a href="http://ryudo.tw/blog/2013/06/07/rubykaigi2013-lt/">Lightning Talk</a>向世界的Rubyist們介紹了Ruby Taiwan社群</li>
<li>七月, 在<a href="https://kktix.com/events/ruby-tuesday-24">Ruby Tuesday 24</a>發表<a href="http://rubytaiwan.tumblr.com/post/55311043584/ruby-tuesday-24">日本行心得</a>, 該場Ruby Tuesday也創下了史上最多與會者的紀錄(報名115, 實到100)</li>
<li>九月, 和<a href="http://blog.eddie.com.tw/">龍哥</a>與<a href="http://blog.taian.su/">泰安</a>共同<a href="http://ryudo.tw/blog/2013/09/14/railsgirls-taipei-01/">舉辦</a>了<a href="http://railsgirls.tw/2013/10/08/rg-taipei1st-record/">第一屆Rails Girls Taipei</a>;  九月底離開Resume Companion</li>
<li>十一月, 舉辦<a href="http://railsgirls.tw/2013/11/29/rg-taipei2nd-record/">第二屆Rails Girls Taipei</a>, 接任<a href="http://rubyconf.tw/">RubyConf Taiwan</a>總召</li>
</ul>


<p>回顧2013, 最多事件發生在經營Ruby社群方面, 雖然從小以來對辦活動或是搞社團都不太熱衷, 參與社群最初的目的也只是想要精進自己的技術和交朋友, 不知不覺Ruby社群就變成生活重心之一了, 參加RubyKaigi 2013期間的所見所聞也對我產生了很大的衝擊, 明年的目標有：</p>

<ul>
<li>成功舉辦RubyConf Taiwan 2014</li>
<li>讓某個該上線的網站上線(秘)</li>
<li>讓上述的網站正常營運</li>
<li>持續經營Rails Girls 社群</li>
<li>在國外的conf發表talk或session</li>
<li>學好日文</li>
<li>學好英文</li>
</ul>


<h1>加油！</h1>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rails Girls Taipei-01 活動主辦心得]]></title>
    <link href="http://ryudo.tw/blog/2013/09/14/railsgirls-taipei-01/"/>
    <updated>2013-09-14T14:39:00+08:00</updated>
    <id>http://ryudo.tw/blog/2013/09/14/railsgirls-taipei-01</id>
    <content type="html"><![CDATA[<p><img src="http://farm6.staticflickr.com/5471/9698784100_dfb2afc625_b.jpg" alt="Group photo of Rails Girls Taipei-01" /></p>

<p>以下是我和<a href="http://blog.eddie.com.tw/">高見龍</a> 以及<a href="http://blog.taian.su/">泰安</a> 共同主辦第一屆<a href="http://railsgirls.tw/">Rails Girls Taipei</a>活動的心得</p>

<h3>Rails Girls社群</h3>

<p>有關於Rails Girls社群的介紹可以參考<a href="http://www.openfoundry.org/index.php?option=com_content&amp;task=view&amp;id=9044&amp;Itemid=4">Open Foundry</a>或 <a href="http://www.inside.com.tw/2013/08/12/rails-girls-taipei-workshop">Inside</a>的介紹, 在此就不再儹述。</p>

<h3>緣起</h3>

<p>女性, 在台灣的程式社群屬於稀有動物的範疇, 一般來說在各大程式研討會中女會眾的比例通常在百分之三或以下, 所以一開始知道有<a href="http://railsgirls.com">Rails Girls</a>這種活動(或著可以說是社群)時並不是特別感興趣; 轉捩點是四月和高見龍一起開<a href="http://blog.eddie.com.tw/2013/04/22/1st-ruby-and-rails-training-course/">有心人課程</a>時, 發現竟然有意外多的女性學員(約佔全部學員的四分之一), 讓我們重新考慮舉辦這個活動的可能性; 研究了一下之後, 發現他是可以自由申請主辦的, 因此在五月初準備Rubykaigi 2013的行程與演講時, 就試著填寫了主站上的申請表單, Rails Girls的創辦人Linda Liukas也很快的就回應我, 讓我加入了世界各地Rails Girls活動的主辦群中。</p>

<p>加入「世界各地的Rails Girls主辦群」之後, 就是可以加入Railsgilrs.com網站的Github Repository, 以及修改或新增網站的內容, 使用Repository內的資源(圖片/素材)之外 還有加入Rails Girls的maillist;  除此之外都要由當地的主辦人自行張羅。</p>

<h3>在日本的見聞</h3>

<p>我在五月底至六月初和高見龍一同前往日本參加<a href="http://ryudo.tw/blog/2013/06/07/rubykaigi2013-lt">Rubykaigi 2013</a>時, 有幸和日本Rails Girls的主辦人<a href="http://www.hsbt.org">柴田博志</a>先生討論了如何教不會程式的女生上手Rails的方式, 他講到了一個重點「藉由copy &amp; paste, 讓學員有成就感」。</p>

<p>在Rubykaigi三天的議程中, 我們觀察到女性會眾的比例是遠超過5%的, 也藉機在現場認識了許多女性會眾, 發現之中甚至有原本不具程式經驗, 卻因為參加過Rails Girls活動後主動來參加RubyKaigi的女會眾; 而在Rubykaigi後一天舉辦的<a href="http://rubyhiroba.org">Ruby Hiroba</a>的主題活動<a href="https://www.facebook.com/Rails%20GirlsMoreExtended">Rails Girls, more extended</a>中, 同行的高見龍也現場觀察了日本這邊的活動情形, 如名稱上的「more extended」所示, 這是普通Rails Girls活動的進階版, 是採取由學員選擇有興趣的主題, 例如前端或後端技術等, 和熟練這些主題的教練一對二或三的教學形式, 在現場就近直接觀查教學的情形, 對於我們日後的主辦也很有幫助; 整個3+1天的活動之中的所見所聞, 都增加了我們的信心和決心。</p>

<p><img src="http://farm8.staticflickr.com/7424/8901595193_1939a4de96_b_d.jpg" alt="Photo with Nakawaza and Yamaneko @Rubykaigi2013" />
(在RubyKaigi會場和Rails Girls的學員中澤(中)以及知名的mrubyist Yamane(右)合照)</p>

<h3>開始籌辦</h3>

<p>從日本回來之後一直忙於各種事件, 直到七月才有空開始, 除了本來就決定要一起主辦的高見龍之外, 剛好社群的朋友泰安對於這個活動都很有興趣, 因此我們就決定一起主辦這個活動。</p>

<p>泰安的夫人本身是一位業餘的畫家, 就請他畫了現在各位看到的這個Logo</p>

<p><img src="http://ryudo.tw/images/rg-taipei.jpg" alt="Rails Girls Taiwan Logo" /></p>

<h4>贊助商</h4>

<p>由於這個活動規定不能向學員收取門票, 所以最重要的是找尋贊助商; 想到之前上課的學生阿姿是國內非常知名且歷史悠久的和女性有關的網站<a href="http://verywed.com">非常婚禮verywed</a>的員工, 於是請她幫忙介紹引薦該公司的老闆與技術主管, 在簡短的會談闡明本活動的宗旨後, 該公司也欣然同意贊助本次活動, 順帶一提的是該公司是台灣極少數以女性員工為主的網路公司, 連程式都是以女性員工佔多數, 感謝非常婚禮的幫忙。</p>

<h4>場地</h4>

<p>一開始由於並不知道會有多少人報名, 決定以小而精的場地為主要的考量, 就選擇了在各大程式語言社群中頗負盛名的<a href="http://clbc.tw">CLBC慶隆商務俱樂部</a>為第一順位的場地選擇; 在談完贊助後立刻前往預約, 也很幸運的預約到了想要的時間; 並且獲得老闆Tyler的同意讓我們用公益團體的優惠價格計費, 在此必需要再次的感謝CLBC。</p>

<p><img src="http://farm3.staticflickr.com/2888/9695456801_7ee681348d_b_d.jpg" alt="Rails Girls Taipei-01 Venue" /></p>

<h4>報名</h4>

<p>事先大家最擔心的就是會沒有學員, 畢竟現狀就如前面所提, 程式社群的女性成員是非常稀少的, 不過事後證明這些擔心都是多餘的; 中午開放報名後, 不到2小時就超過了150人, 更在第二天下午時已經超過了320人, 只好提前關閉註冊, 接下來篩選學員的工作反而是最花時間的, 大概花了將近十天在review報名資料上, 由於場地限制的因素, 最後只能選出31位的學員。</p>

<p>學員的資歷方面真的是臥虎藏龍的等級, 有位學員甚至曾經在大陸的百度這種超巨型網路公司工作過, 也有學員特地從台中兩天都當日搭高鐵往返參加的, 最值得一提的是一位來自花蓮數位機會中心的老師, 為了知識傳承, 特地從東部海邊北上來參加活動。</p>

<h4>選取標準</h4>

<p>如同國外創立這個活動的原意, 加上參考日本方面的選取標準後, 我們希望選擇的是比較沒有其它程式經驗的人, 然後重要的是, 在自介中說明以下兩件事：</p>

<ol>
<li>為什麼妳想參加這個活動？</li>
<li>讓我們了解妳是一個怎樣的人？</li>
</ol>


<h4>事前準備</h4>

<p>雖然之前已經有一點教Ruby的經驗, 不過教完全新手的事, 從學生時代以後就沒體驗過, 這次我們決定由一位教練負責2位學員, 因此從社群徵求了15位朋友來擔任教練的工作, 在Ruby Tuesday#25的會後進行了第一次的討論; 決定了教學方向後, 教材的部份就由泰安負責主編, 其他教練協助編輯, 成果可以在<a href="https://github.com/railsgirls-taiwan">Github</a>上看到; 加上一位公費留學過歐洲, 英文非常流利的教練<a href="https://twitter.com/JuanitoFatas">@JuanitoFatas</a>幫忙翻譯了<a href="http://guides.railsgirls.tw">Rails Girls Guides</a>為主的很多文件, 讓我們雖然是首次主辦, 但各方面規模與完整性並不輸給國外。</p>

<h4>現場狀況</h4>

<p>雖然已經主辦過如<a href="http://ryudo.tw/blog/2013/04/23/rubyconftw-2012-memories-1">RubyConf Taiwan</a> 這樣的年度國際研討會, 第一次主辦完全以女性為主的活動, 不免還是會擔心出席率等等的問題; 不過活動一切順利, 教練和學員的互動也出乎意外的良好, 可能是因為女生之間一起學習的關係, 一般程式社群中新人女會眾的集體沉默現象在這邊完全不復見, 學員都全程參與, 也沒有遲到早退的問題, 真是可喜可賀。</p>

<p><img src="http://farm4.staticflickr.com/3702/9698686706_29d4fa9f51_b_d.jpg" alt="現場1" />
<img src="http://farm4.staticflickr.com/3671/9698677328_4ba4ab1959_b_d.jpg" alt="現場2" /></p>

<h4>After Party</h4>

<p>教學之外, 這個活動的目的之一是促進學員和教練之間的互動, After Party也列在官方的Guides內, 因此事先就宣布並徵詢學員的參與意願; 場地方面, 想要維持品質以及營造互動的氛圍, 決定要以Lounge Bar為主, 經友人推薦之下, 選擇了費用上不算便宜的<a href="https://www.facebook.com/Tribeca.TPE">TRIBECA</a>, 由於學員需要自費, 原本以為會變成教練與Staff們為主的聚會, 最後還是有超過一半的學員參加, 大家也聊到了十點才散會。</p>

<p><img src="http://farm4.staticflickr.com/3794/9850705143_0b013f3e26_b_d.jpg" alt="Rails Girls Taipei After Party 2" />
<img src="http://farm4.staticflickr.com/3793/9850684473_9c65e3c4d6_b_d.jpg" alt="Rails Girls Taipei After Party 3" />
<img src="http://farm6.staticflickr.com/5445/9851366586_f2b7fd1ed7_b_d.jpg" alt="Rails Girls Taipei After Party" /></p>

<h3>感想</h3>

<p>Ruby真的是一門神奇的語言啊, 原本只是基於想要改變社群性別分布不均這個現狀的心情, 從國外引進並舉辦了這個活動, 卻得到了遠遠出乎意料的反應與成果, 看來21世紀的程式學習趨勢真的不是說說而已, 今後也會繼續這個活動下去, 感謝活動過程中一路相挺的朋友們, 謝謝大家。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to migrate a PostgreSQL DB with many schemas in a multenancy Rails application]]></title>
    <link href="http://ryudo.tw/blog/2013/08/11/migrate-multi-schemas-into-a-rails-application/"/>
    <updated>2013-08-11T21:38:00+08:00</updated>
    <id>http://ryudo.tw/blog/2013/08/11/migrate-multi-schemas-into-a-rails-application</id>
    <content type="html"><![CDATA[<p>PostgreSQL的schema是一個非常方便的功能, 適合拿來做所謂的<a href="http://www.arthurtoday.com/2010/02/multi-tenant-application-multitenancy.html#.UgeXg2T08Rw">Multi-Tenancy</a>類服務; 例如無名或Pixnet這類的BSP(Blog Service Provider)或是像我的FREEBBS的免費論壇服務(Forum Service Provider), 通常稱為SAAS(Software As A Service)系統, 可以把N個相同結構的schema放在同一個資料庫裡面; 比起MySQL只能分別放在不同的資料庫裡會有很多好處。</p>

<p>假設今天我用PostgreSQL的schema功能來做一個BSP服務的話, DB內的schema會分成兩大類：</p>

<ul>
<li>管理用schema(只有一個)</li>
<li>Blog Schema(有無數個, 每個的結構相同)</li>
</ul>


<p>一般狀況下, 我們在使用ActiveRecord連接PosttgreSQL時可以在連接選項設定使用Schema, 像這樣：</p>

<figure class='code'><figcaption><span>database.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><span class='line'>  <span class="l-Scalar-Plain">adapter</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">postgresql</span>
</span><span class='line'>  <span class="l-Scalar-Plain">encoding</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">unicode</span>
</span><span class='line'>  <span class="l-Scalar-Plain">database</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">SHOPON_development</span>
</span><span class='line'>  <span class="l-Scalar-Plain">pool</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">5</span>
</span><span class='line'>  <span class="l-Scalar-Plain">schema_search_path</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">base, blog1</span>
</span></code></pre></td></tr></table></div></figure>


<p>schema_search_path的預設值是public, 如果照以上設定, 當你執行任何migration時會先從base這個schema執行起, 也就是所有的migration都只會跑在base這個schema上面,</p>

<p>但場景回到Rails/ActiveRecord上, 假如你要做一個BSP, 一般而言你有以下幾種方式：</p>

<ol>
<li>管理端(管理BSP的)和服務端(Blog服務本身)分別各自一個Rails Application目錄, 然後各有各的migrate</li>
<li>將兩端放在同一個Rails App裡</li>
</ol>


<p>如果用一般的方式migrate, Rails會依照你database.yml裡設定的schema_search_path的順序找第一順位來執行migrate; 這樣你要如何migrate你的資料到不同schema呢？</p>

<p>今天要講的就是將兩端放在同app裡的方式, 也就是</p>

<ol>
<li>在migrate檔內設定只能在服務端schema或是管理端schema執行</li>
<li>有<strong>單獨migrate管理端</strong>和<strong>單獨migrate服務端</strong>的功能</li>
</ol>


<p><strong><em>實現1.的方式如下</em></strong>：</p>

<figure class='code'><figcaption><span>migrate_control_side.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>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="k">class</span> <span class="nc">CreateSites</span> <span class="o">&lt;</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Migration</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">change</span>
</span><span class='line'>    <span class="k">if</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">schema_search_path</span> <span class="o">==</span> <span class="s1">&#39;base&#39;</span> <span class="c1">#base為管理端schema</span>
</span><span class='line'>      <span class="n">create_table</span> <span class="ss">:sites</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
</span><span class='line'>        <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:subdn</span>
</span><span class='line'>        <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:name</span>
</span><span class='line'>        <span class="n">t</span><span class="o">.</span><span class="n">timestamps</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><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>簡單來說就是當現在的 schema_search_path 不等於base則不執行create_table的動作; 如果是服務端, 則反過來設定schema_search_path不為base或public即可, 更進一步的可以將這兩種檢查寫成ActiveRecord::Migration的module, 像這樣：</p>

<figure class='code'><figcaption><span>multitenancy_migration.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='rb'><span class='line'><span class="k">module</span> <span class="nn">ActiveRecord::MultitenancyMigration</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">must_migrate_in_base</span> <span class="c1">#管理端</span>
</span><span class='line'>    <span class="k">if</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">schema_search_path</span> <span class="o">==</span> <span class="s1">&#39;base&#39;</span>
</span><span class='line'>      <span class="k">yield</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">must_migrate_in_site</span> <span class="c1">#服務端</span>
</span><span class='line'>    <span class="n">schema_search_path</span> <span class="o">=</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">schema_search_path</span>
</span><span class='line'>    <span class="k">if</span> <span class="o">!</span><span class="n">schema_search_path</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s1">&#39;base&#39;</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">schema_search_path</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s1">&#39;public&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="k">yield</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><span class='line'>
</span><span class='line'><span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Migration</span><span class="o">.</span><span class="n">class_eval</span> <span class="k">do</span>
</span><span class='line'>  <span class="kp">include</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:MultitenancyMigration</span>
</span><span class='line'>  <span class="kp">extend</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:MultitenancyMigration</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>由於migration檔的內部可能是以self.up(class method)或是up(instance method)的方式編寫, 因此需要同時include和extend這個模組。</p>

<p><strong><em>實現2.的方式如下</em></strong>：</p>

<p>需要建立for 管理端以及 for 服務端的task 來migrate 各自的schema</p>

<figure class='code'><figcaption><span>base.rake</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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">namespace</span> <span class="ss">:base</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">task</span> <span class="n">migrate_db</span><span class="p">:</span> <span class="ss">:environment</span> <span class="k">do</span>
</span><span class='line'>    <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">schema_search_path</span> <span class="o">=</span> <span class="s1">&#39;base&#39;</span>
</span><span class='line'>    <span class="ss">Rake</span><span class="p">:</span><span class="ss">:Task</span><span class="o">[</span><span class="s1">&#39;db:migrate&#39;</span><span class="o">].</span><span class="n">invoke</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">task</span> <span class="n">rollback_db</span><span class="p">:</span> <span class="ss">:environment</span> <span class="k">do</span>
</span><span class='line'>    <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">schema_search_path</span> <span class="o">=</span> <span class="s1">&#39;base&#39;</span>
</span><span class='line'>    <span class="ss">Rake</span><span class="p">:</span><span class="ss">:Task</span><span class="o">[</span><span class="s1">&#39;db:rollback&#39;</span><span class="o">].</span><span class="n">invoke</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>site.rake </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">namespace</span> <span class="ss">:site</span> <span class="k">do</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">check_subdn_exists</span>
</span><span class='line'>    <span class="k">if</span> <span class="no">ENV</span><span class="o">.</span><span class="n">has_key?</span><span class="p">(</span><span class="s1">&#39;SUBDN&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">schema_search_path</span> <span class="o">=</span> <span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;SUBDN&#39;</span><span class="o">]</span>
</span><span class='line'>      <span class="k">yield</span>
</span><span class='line'>    <span class="k">else</span>
</span><span class='line'>      <span class="nb">puts</span> <span class="s2">&quot;Please assign SUBDN first!&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>  <span class="n">desc</span> <span class="s1">&#39;Migrate Database of Individual site, have to assign SUBDN paramater!&#39;</span>
</span><span class='line'>  <span class="n">task</span> <span class="n">migrate_db</span><span class="p">:</span> <span class="ss">:environment</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">check_subdn_exists</span> <span class="k">do</span>
</span><span class='line'>      <span class="ss">Rake</span><span class="p">:</span><span class="ss">:Task</span><span class="o">[</span><span class="s1">&#39;db:migrate&#39;</span><span class="o">].</span><span class="n">invoke</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">desc</span> <span class="s1">&#39;Rollback migration of single site&#39;</span>
</span><span class='line'>  <span class="n">task</span> <span class="n">rollback_db</span><span class="p">:</span> <span class="ss">:environment</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">check_subdn_exists</span> <span class="k">do</span>
</span><span class='line'>      <span class="ss">Rake</span><span class="p">:</span><span class="ss">:Task</span><span class="o">[</span><span class="s1">&#39;db:rollback&#39;</span><span class="o">].</span><span class="n">invoke</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>簡單來說就是在migrate前先切換schema, 然後用Rake的指令呼叫原本的db:migrate/rollback出來, 當然你也可以寫一個task是去掃現存的服務端列表然後再各自migrate, 如果要寫在controller或model的話, 則必需先require rake然後再load Rakefile才行。</p>

<p>以上</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Introduce Ruby Taiwan Community@RubyKaigi 2013[EN,CH]]]></title>
    <link href="http://ryudo.tw/blog/2013/06/07/rubykaigi2013-lt/"/>
    <updated>2013-06-07T20:57:00+08:00</updated>
    <id>http://ryudo.tw/blog/2013/06/07/rubykaigi2013-lt</id>
    <content type="html"><![CDATA[<p>非常榮幸本次有機會可以和台灣Ruby社群的朋友一起參加世界級的Ruby研討會<a href="http://rubykaigi.org/2013">RubyKaigi2013</a>, 做為台灣Ruby社群的主持人之一, 既然參加了就想要讓世界的Ruby朋友們知道Ruby Taiwan社群的存在, 因此在LT徵稿前就打算要投稿這個主題了.</p>

<hr />

<p>It&#8217;s my pleasure to join the world-class Ruby seminar <a href="http://rubykaigi.org/2013">RubyKaigi2013</a>, as one of the organizers of Ruby Taiwan community, I wish to let the world know the exist of our community, so I plan to submit this LT.</p>

<p>由於是第一次在海外以英文發表, 又是只有五分鐘的LT, 如果用一般的形式會很難控制時間, 因此就想到了高橋流的方式, 在準備的過程中不斷反覆觀看高橋征義在台灣的LT影片以及簡報來練習; 對於鋪梗也是費盡心思, 感謝<a href="https://twitter.com/ihower">@ihower</a>在去年RubyConf Taiwan 2012的<a href="http://www.slideshare.net/ihower/rubyconf-taiwan-2012-opening-closing">十六字箴言</a>, 以及在<a href="http://magazine.rubyist.net/?0041-RubyTaiwan2012">Rubyist Magazine</a>將其日語漢字化的柴田先生<a href="https://twitter.com/hsbt">@hsbt</a>; 另外由於會眾日本人佔多數, 在講稿上採取英日文並行的方式, 這點要特別再特別的感謝旅居日本的台灣人Rubyist侯大偉<a href="https://twitter.com/davidhou_tw">@davidhou_tw</a>的全力支持, 大偉不但幫我翻譯, 甚至還請了日本朋友幫忙review, 我跟他致謝時他說：「還是慎重點好 畢竟你代表台灣宣傳阿」這句話時, 真的整個超感動又熱血的.</p>

<hr />

<p>Since this is my first time to speak outside of Taiwan and it&#8217;s a 5 mins LT session, I decided to use the Takahashi-method on my talk. I watch Takahashi-san&#8217;s slide and screencasts again and again to meditate and practice my speech. Special thanks to @ihower&#8217;s <a href="http://www.slideshare.net/ihower/rubyconf-taiwan-2012-opening-closing">opening slide at RubyConf Taiwan 2012</a> and <a href="(https://twitter.com/hsbt">@hsbt</a>&#8217;s <a href="http://magazine.rubyist.net/?0041-RubyTaiwan2012">Japanese translation on Rubyist Magazine</a> gave me some content on the slide. I write both Japanese and English on my slide because the biggtest part of audience are Japanese. I have to appreciate <a href="https://twitter.com/davidhou_tw">David Hou</a> who is a Taiwanese Rubyist working and living in Japan for translating my slide to Japanese. He even asked help from a Japanese friend. He said to me: &#8220;We should be more careful, you represent the Ruby Taiwan community after all&#8221; when I expressed my thank to him. He really moved me!</p>

<p>另外一個最後引起日本朋友們關注的就是桐島梗了, 其實會有這個梗是因為自從去年Rubyconf Taiwan 2012後就有在關注日本Ruby大神們的推特, 適逢今年3月時日本舉辦的<a href="http://magazine.rubyist.net/?0042-OoedoRubyKaigi03Report">大江戶RubyKaigi03</a>其中一場由CRuby GC的作者中村成洋<a href="https://twitter.com/nari3">@nari3</a>的演講<a href="http://www.slideshare.net/authorNari/ruby-17269278">桐島、Rubyやめるってよ</a>持續引起大神們的討論, 看了簡報之後雖然不是很懂但是對其中引用的電影<a href="http://www.ghfff.org.tw/program/content.aspx?id=521">聽說桐島退社了</a>感到興趣, 看過之後再回頭看中村的簡報就能夠理解那些梗了, 個人以為那句「<a href="http://imgur.com/Z8m9zkn">戰鬥吧！這裡是我們的世界</a>」是整個電影, 同時也是我自己參與社群經營活動的精神之體現, 作為結尾是非常適合的.</p>

<hr />

<p>I found the most eye-catching point of my presentation for Japanese is the 「Kirishima」&#8217;s ネタ. In fact I started to follow many Japanese Rubyist&#8217;s twitter after the RubyConf Taiwan 2012 last year. I noticed <a href="https://twitter.com/nari3">Narihiro Nakamura</a>&#8217;s presentation named 「<a href="http://www.slideshare.net/authorNari/ruby-17269278">Kirishima, stop using Ruby</a>」 which is retwteed many times after the 「Oedo RubyKaigi 03」 on March this year. I am extremely interested by the slide&#8217;s subject which is a movie named 「The Kirishima Thing」, so I can  understanded what Nakamura expressed in his slide after watched the movie and deeply impressed by it. I decided to use the most important line of the movie &#8220;Fighting, this is our world!&#8221; as the last page of my slide because I think it is the spirit of both the movie and the reason of why I join the operation of our community.</p>

<p>上台前一直很擔心這些梗會沒有用, 前一天晚上由於和龍哥隔天都要上台的關係緊張到幾乎沒睡; 不過現場的反應真是超乎想像意外的好, 結束後也陸續接到幾位日本朋友們的鼓勵, 真的非常窩心, 感謝你們!</p>

<hr />

<p>I almost can&#8217;t sleep on the eve of LT and worried about if my slide can&#8217;t attract the audience. Fortunately I finished the speech and it seemed the audience&#8217;s reaction was good. I must show my gratitude for beging metioned by many Japanese Ruby friends on Twitter as below:</p>

<blockquote class="twitter-tweet" data-conversation="none" lang="zh-tw"><p>@<a href="https://twitter.com/ryudoawaru">ryudoawaru</a> ありがとうございました！lightning talk最高でした！</p>&mdash; Akira Matsuda (@a_matsuda) <a href="https://twitter.com/a_matsuda/status/340776485826740225">2013年6月1日</a></blockquote>


<blockquote class="twitter-tweet" lang="zh-tw"><p>練度たかい <a href="https://twitter.com/search/%23rubykaigi">#rubykaigi</a> <a href="https://twitter.com/search/%23rubykaigia">#rubykaigia</a></p>&mdash; Kakutani Shintaro (@kakutani) <a href="https://twitter.com/kakutani/status/340393348638601216">2013年5月31日</a></blockquote>


<blockquote class="twitter-tweet" lang="zh-tw"><p>I would like to go to RubyConf Taiwan 2014〜</p>&mdash; SHIBATA Hiroshi (@hsbt) <a href="https://twitter.com/hsbt/status/341113796158439424">2013年6月2日</a></blockquote>


<blockquote class="twitter-tweet" lang="zh-tw"><p>Awesome taiwan ruby community! @<a href="https://twitter.com/ryudoawaru">ryudoawaru</a></p>&mdash; Tatsuya Sato (@sato_ryu) <a href="https://twitter.com/sato_ryu/status/340393351146778624">2013年5月31日</a></blockquote>


<blockquote class="twitter-tweet" data-conversation="none" lang="zh-tw"><p>@<a href="https://twitter.com/ryudoawaru">ryudoawaru</a> わたしも小学生の時からのファンです！ 素敵なLTでした、TwのRubyカンファレンスに行ってみたくなりました :)</p>&mdash; やきとりい (@yotii23) <a href="https://twitter.com/yotii23/status/340406791693279233">2013年5月31日</a></blockquote>


<blockquote class="twitter-tweet" lang="zh-tw"><p>@<a href="https://twitter.com/ryudoawaru">ryudoawaru</a> 良いLTでした(бвб)！</p>&mdash; すずきみほ SUZUKI Miho (@adzuki34) <a href="https://twitter.com/adzuki34/status/340393460668432384">2013年5月31日</a></blockquote>


<blockquote class="twitter-tweet" lang="zh-tw"><p>@<a href="https://twitter.com/ryudoawaru">ryudoawaru</a> LT素晴らしかったです！ありがとうございました！</p>&mdash; Yuki Nishijima (@yuki24) <a href="https://twitter.com/yuki24/status/340784167895838720">2013年6月1日</a></blockquote>


<blockquote class="twitter-tweet" lang="zh-tw"><p>.@<a href="https://twitter.com/ryudoawaru">ryudoawaru</a> さんが <a href="https://twitter.com/search/%23rubykaigi">#rubykaigi</a> 2日目のLTでスライドに桐島を使っていたのは、@<a href="https://twitter.com/nari3">nari3</a> の大江戸03のスライドを見て興味を持ち、映画を探して観て大好きになったからだとか(台湾語字幕あるそうです)。台湾rubyistに桐島届いてた！</p>&mdash; O-Show (@oshow) <a href="https://twitter.com/oshow/status/341110877375840256">2013年6月2日</a></blockquote>


<script async src="http://ryudo.tw//platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>神奇的是, 在LT投影片上傳slideshare後的隔天竟然登上了slideshare的「Hot on Facebook」首頁排行榜, 真的是又驚又喜</p>

<hr />

<p>It was a miracle that on the third day of RubyKaigi2013, my slide was in the 「Hot in Facebook」 area of Slideshare&#8217;s homepage.</p>

<center><img src="http://i.imgur.com/rN7xNwl.png" style="max-width:720px;" /></center>


<p>感謝<a href="https://twitter.com/takai">高井先生</a>的照片, 拍的非常好.</p>

<hr />

<p>Thanks to the high quality photo taken by <a href="https://twitter.com/takai">Naoto Takai</a>.</p>

<center><img src="http://farm6.staticflickr.com/5469/8905326085_5f217d6665_c.jpg"/></center>


<p>這趟日本行真的是收獲多多, 接下來還會有幾篇文章介紹; 整個從準備到上台的過程中, 心裡一直想就大偉的話, 要讓世界知道Ruby Taiwan社群的存在, 今後一樣會持續努力</p>

<hr />

<p>I learn so much on Japan this time, and I will write many blog posts to represent my journey. On the process of preparing the presentation, I always remember what David said and try my best to let the attendee know what we(Ruby Taiwan community) do and I will continue my work in the future.</p>

<h3>Thanks to all awesome staffs of Rubykaigi and community friends in Japan, また台湾で会お！</h3>

<p>附上簡報檔以及當天Live如下：</p>

<center>
<iframe src="http://www.slideshare.net/slideshow/embed_code/22236968?rel=0" width="597" height="486" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="http://www.slideshare.net/ryudoawaru/introduce-ruby-taiwanrubykaigi2013" title="Introduce Ruby Taiwan@Rubykaigi2013" target="_blank">Introduce Ruby Taiwan@Rubykaigi2013</a> </strong> from <strong><a href="http://www.slideshare.net/ryudoawaru" target="_blank">Mu-Fan Teng</a></strong> </div>
<iframe width="480" height="302" src="http://www.ustream.tv/embed/recorded/33573701/highlight/367455?v=3&amp;wmode=direct" scrolling="no" frameborder="0" style="border: 0px none transparent;">    </iframe>
<br /><a href="http://www.ustream.tv/" style="padding: 2px 0px 4px; width: 400px; background: #ffffff; display: block; color: #000000; font-weight: normal; font-size: 10px; text-decoration: underline; text-align: center;" target="_blank">Video streaming by Ustream</a>
</center>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[達人出版会徵求翻譯以及校稿志工事宜]]></title>
    <link href="http://ryudo.tw/blog/2013/05/02/tatsu-zine-translator-recruitment/"/>
    <updated>2013-05-02T12:00:00+08:00</updated>
    <id>http://ryudo.tw/blog/2013/05/02/tatsu-zine-translator-recruitment</id>
    <content type="html"><![CDATA[<p>大家好：</p>

<p><a href="http://tatsu-zine.com">達人出版会</a>是由日本知名Rubyist, 也是高橋流簡報術的作者「<a href="http://d.hatena.ne.jp/takahashim/">高橋征義</a>」成立, 目的是透過實踐「<a href="https://leanpub.com/manifesto">敏捷出版</a>」的方式出版技術系的日文純電子書籍, 這邊有一份非常詳盡的<a href="http://www.newcreator.com/?p=995">介紹文章</a></p>

<p>最早知道這個網站是在<a href="http://rubyconf.tw/2012/">RubyConf Taiwan 2012</a>時<a href="http://www.youtube.com/watch?v=cPh1q0D10Wg">高橋的LT</a>時提及的</p>

<p>由於個人對於其中一些在台灣可以稱為是非主流或不可能出版的書籍有興趣, 因此日前OSDC.tw 2013時, 在席間和高橋提到是否有機會將其中一些書籍翻譯成中文版, 甚至是在該平台出版中文原生電子書的事情, 沒想到高橋的回應意外的積極, 於是就不自量力的在高橋先生的首肯之下接下了這個任務, 目前正在募集譯者以及校稿志工</p>

<h4>譯者</h4>

<ul>
<li>懂日文, 基本上能看得懂日文技術書輯的程度即可</li>
<li>懂一定程度的技術, 在達人出版會的架構中, 會有叫作「Reviewer」的校稿志工擔任實體出版社中編輯的任務, 因此譯者即使不是技術方面的強者也沒有關係</li>
<li>最重要的就是興趣, 有愛最重要</li>
<li>既然書有賣錢, 因此譯者是有酬勞的, 目前規劃是用計件的方式, 不過如果想用版稅的方式也是可以討論的</li>
</ul>


<h4>校稿志工</h4>

<ul>
<li>對書本相關的技術有一定程度的認識</li>
<li>在翻譯的過程中協助譯者</li>
<li>校稿工作</li>
</ul>


<p>對譯者和校稿志工們而言, 線上出版和實體出版最大的不同就是書籍本身可以一直改版, 所以不會有實體書那樣的壓力; 雙方協同進行翻譯工作可以同時提升日文以及技術能力, 名字會列在書上也算是一個成就.</p>

<p>下面是目前我覺得比較有特色可以翻譯的書籍：</p>

<ul>
<li><a href="http://tatsu-zine.com/books/scheme-in-ruby">つくって学ぶプログラミング言語　RubyによるScheme処理系の実装</a></li>
<li><a href="http://tatsu-zine.com/books/chef-solo">入門Chef Solo - Infrastructure as Code</a></li>
<li><a href="http://tatsu-zine.com/books/llvm">きつねさんでもわかるLLVM</a></li>
<li><a href="http://tatsu-zine.com/books/fuelphpadvent2012">FuelPHP Advent Calendar 2012</a></li>
<li><a href="http://tatsu-zine.com/books/winrubybuild">Ruby環境構築講座 Windows編</a></li>
<li><a href="http://tatsu-zine.com/books/g1gc">徹底解剖「G1GC」 アルゴリズム編</a></li>
<li><a href="http://tatsu-zine.com/books/objc">エキスパートObjective-Cプログラミング ― iOS/OS Xのメモリ管理とマルチスレッド</a></li>
</ul>


<p>有意者請mail: ryudoawaru at gmail.com 給我, 或在下面留言</p>

<p>目前(5/3)為止的募集情況：
校稿志工x3(包括我), 從開始募集譯者一天竟然已經超過10位, 由於報名情形遠超乎想像, 因此之後將請報名者<a href="http://registrano.com/events/tatsuzine">至此填寫基本資料</a>後再試翻作為參考, 謝謝大家！</p>
]]></content>
  </entry>
  
</feed>
