慕凡(@ryudoawaru)'s blog

目前還沒想到

自動化測試 Rails 中的 URL HELPER

| Comments

前言:

最近在某個和客戶共同開發的專案中,遇到了以下的情形:

  1. 專案的 layout / view 經過大幅的改版
  2. 改版是把舊 layout(以下簡稱 ver1)的大部份功能改出一份新版 layout / view / controller(以下稱 ver2)
  3. 改版後幾乎沒有移除 ver1 重複的部份,因此系統中存著很多其實用不到的 view / controller / route
  4. 又因為改版後不想改變在 production env 的 url,所以在路由設定中用了大概是類似的架構:
    • Development 中有 /ver1 和 /ver2 兩個 route namespace,而且有 base uri,意即可能會有 /ver1/products 和 /ver2/products
    • Production 中,這兩個 namespace 的 base uri 會被消除,舉例來說,如果遇到 /products 的 request,系統會先找 /ver2 有沒有 /products,有的話會先使用,沒有再去找 /ver1

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

執行:

基本上就是高科技手工業,程序如下:

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

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

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

於是想到,是否可以將程式中所有用到的 url helper method 集合起來一一做檢查呢?最後想到的解法大意如下:

  1. 用文字搜尋的程式,以正規表示式去找出程式碼中使用的 url helper method
  2. 將找到的 method 集合產生列表
  3. 用列表產生 it 區塊
  4. it 區塊中使用 helper spec 去測試 view context 中是否有這些 method

文字搜尋採用目前比較流行的 ack,好處是除了速度快之外又是 Perl 版的 Regexp,比 egrep 內建的更貼近 Ruby 使用的版本

1
ack --noheading -h '[^A-Za-z0-9_.].((ver1|ver2)[\\w_]+?\_(url|path))' app/ --output '$1' | sort | uniq

使用的 ack 參數如下:

  • 正規表示式為:[^A-Za-z0-9_.].((ver1|ver2)[\\w_]+?\_(url|path))
  • –noheading 不顯示檔案名在頭
  • -h 不顯示檔名在左邊
  • –output ‘$1’ 只顯示批配的第 1 項

測試的程式大概長的像這樣:

1
2
3
4
5
6
7
8
9
10
RSpec.describe ApplicationHelper, :type => :helper do
  fn = "tmp/url_helpers.txt"
  cmd = "ack --noheading -h '[^A-Za-z0-9_.].((ver1|ver2)[\\w_]+?\_(url|path))' app/ --output '$1' | sort | uniq > #{fn}"
  system cmd
  File.read(fn).split.each do |url_helper_name|
    it "Url helper #{url_helper_name} should be available" do
      helper.respond_to?(url_helper_name.to_sym).should be(true)
    end
  end
end

這樣一跑完就可以放心了。

在 Mac / Homebrew 下升級 PostgreSQL 從 9.3 到 9.4

| Comments

前言

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

升級的方式有兩種:

  • 將原本的資料執行 pg_dumpall 後再 restore 回去
  • pg_upgrade 命令從舊的資料檔產生出新版本的資料檔。

這邊要講的是第二種情形。

環境限定:

  • 可執行 Homebrew 的 MacOS 環境
  • 原 PostgreSQL 為 Homebrew 安裝,9.3.x 版

步驟

  1. 安裝新的 PostgreSQL
    1
    2
    
    brew update
    brew install postgresql
    
  2. 停止現在的 PostgreSQL Daemon
    1
    
    launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
    
  3. 建立 9.4 的資料庫檔案
    1
    
    initdb /usr/local/var/postgres9.4 -E utf8
    
  4. 使用 pg_upgrade 指令升級 舊PG的資料檔案到 9.4,注意這邊的 9.3.5_1 和 9.4.0 是會依照你的舊版本和實際安裝的新板本的版號而有差異的
    1
    2
    3
    4
    5
    
    pg_upgrade -v \
        -d /usr/local/var/postgres \
        -D /usr/local/var/postgres9.4 \
        -b /usr/local/Cellar/postgresql/9.3.5_1/bin/ \
        -B /usr/local/Cellar/postgresql/9.4.0/bin/
    
  5. 將舊資料檔備份,並且讓新資料檔的目錄更名使之變成預設的資料檔
    1
    2
    3
    
    cd /usr/local/var
    mv postgres postgres9.3
    mv postgres9.4 postgres
    
  6. 重啟 PostgreSQL
    1
    
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
    
  7. 檢查 /usr/local/var/postgres/server.log 檔是否有正常啟動 server
  8. 如果原本有安裝 pg GEM 的話要重新安裝

以上!

銘謝文–RubyKaigi 2014之旅以及 Rails Girls Taipei 獎助金計劃

| Comments

緣起

由於有了去年第一次和高見龍等人一同參加 RubyKaigi 2013 的經驗,因此當確定今年的 RubyKaigi時程後,就非常的期待有機會能夠再次參加這場 Ruby世界最重要的研討會。

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

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

在七月籌備 RG Taipei-4 時,透過 E-Mail 向相澤先生詢問此事之後,得到了肯定的回覆,於是就著手開始選拔辦法

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

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

成員

Photo by Igarashi Kuniaki

  1. 龍哥
  2. 大兜(講者)
  3. Bruce(講者)
  4. Mason
  5. Annie(RG 獎助金計劃獲選者)
  6. 阿旺(RG 獎助金計劃獲選者)
  7. Lena(RG 獎助金計劃獲選者)

參加了哪些活動

可參考下列文章與分享:

  • 同上的影片紀錄

結語

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

特別感謝

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

RubyConf Taiwan 2014

| Comments

按照往年的慣例,這篇也拖稿了超級久。

時間和場地

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

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

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

這次場地的優點:

  1. 夠大
  2. 兩個場地後面是相通的
  3. 很多廳

缺點:

  1. 休息區的位子較少
  2. 大禮堂和其它廳的人數差距太大(1000 : 240)不過由於我們只有 290 左右的會眾,因此不是問題

Linda Liukas

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

其實有趣的是 2014 的 RubyKaigi 也有 RG 相關的議程,看來這應該是趨勢無誤。

設計

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

Mobile APP

在一個不是以 APP 為主題的 conf 推出了雙平台的 APP,要感謝擔任 iOS 開發的龍哥以及幾位 Alphacamp 的學員,還有擔任 Android 開發的阿旺以及協助她的佳緯。

CFP & 講者

這次的 CFP 讓我最意外的是,在沒有招待食宿機票的狀況下,投稿者裡面竟然有超過一半的外國投稿,有鑑於此,後來也開放了讓這些講者的所屬單位掛上了特別的 Speaker Sponsorship 作為一種回饋。

講者(包括 Keynote)來自於包括台灣在內有七個不同的國家,分佈為:

  1. 台灣:10
  2. 日本:8
  3. 美國:7
  4. 香港:1
  5. 中國:1
  6. 芬蘭:1
  7. 比利時:1
  8. 新加坡:1

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

食物 & 飲料

抱歉第一天搞砸了,還好第二天的便當大家還算滿意。

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

Party

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

語言與國際化

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

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

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

Rails Girls 特別講座

原本在 conf 的隔日,打算按照日本的 RubyHiroba 的方式,舉辦一個 Unconference 的活動並且混合 RG,不過在和出身於 RG 的 Hazel 討論後,決定趁著這次邀請到 Linda(Rails Girls Co-Founder) 的機會來舉辦一場特別的座談會活動,也因此促成了「姺語言力-程式新市場,女孩新火花」的舉辦。

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

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

同時也要感謝 Inside 的編輯,也是 RG 校友的 Liz 對 Linda 進行的深度採訪,還有贊助拍攝的 Retina Studio

Rails Girls Staffs

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

同時這個亮點也引起了在場許多外國朋友的注意,也進而造就了日後的 RubyKaigi 獎助金計劃

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

總結

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

Next Time?

預計於 2015.09,敬請期待!

PostgreSQL Materialized View簡介

| Comments

最近在開發某個主力產品時遇到了一個問題,就是當我們在後台編輯一些資料,包含新增 / 修改 / 刪除 ,然後在沒有完成所有編輯前不想讓修改中的資料立刻在前台生效,正在苦思如何完成這項功能時,發現了PostgreSQL有一個超好用的功能叫「Materialized View」,於是就開始survey看看。

Database View

Wikipedia中的說明為:

1
檢視表 (View) 是在關聯式資料庫中,將一組查詢指令構成的結果集,在實體資料表中的改變都可以立刻反應在檢視表中

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

我們會用以下的方式建立一個View:

1
2
3
4
5
6
7
8
9
CREATE VIEW orders_products_users AS
SELECT
orders.user_id,
users.name,
orders.product_id,
products.name
FROM
orders JOIN users ON users.id = orders.user_id,
JOIN products ON products.id = orders.product_id

以後我們要使用這個view時只要:

1
SELECT * FROM orders_products_users;

即可

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

Materialized View(以下簡稱M-View)

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

Postgresql的Materialized View

這個功能原本是出自於Oracle,號稱「開源的Oracle」的PostgreSQL也在本文撰時最新的穩定版本9.3加入了該功能,參考資料

建立Materialized View

1
2
3
CREATE MATERIALIZED VIEW table_name
    AS query
    [ WITH [ NO ] DATA ]

例如:

1
CREATE MATERIALIZED VIEW mymatview AS SELECT * FROM mytab;

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

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

更新Materialized View

1
REFRESH MATERIALIZED VIEW  M-View的名稱

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

移除Materialized View

1
DROP MATERIALIZED VIEW  M-View的名稱 [CASCADE | RESTRICT]

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

Materialized View的注意事項

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

Materialized View的用途

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

範例

今天假設有如下的表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE spree_products
(
  id serial NOT NULL,
  name character varying(255) NOT NULL DEFAULT ''::character varying,
  description text,
  available_on timestamp without time zone,
  deleted_at timestamp without time zone,
  slug character varying(255),
  meta_description text,
  meta_keywords character varying(255),
  tax_category_id integer,
  shipping_category_id integer,
  created_at timestamp without time zone,
  updated_at timestamp without time zone,
  CONSTRAINT spree_products_pkey PRIMARY KEY (id)
)

然後我們建立如下的M-View

1
2
CREATE MATERIALIZED VIEW spree_products_mview AS
 SELECT * FROM spree_products;

然後我們看現在的 spree_products表內容如下: 此時table和M-View的資料應該是一致的,此時我們將資料表的一些資料刪除:

1
DELETE FROM spree_products WHERE id = 16;

此時id為16的紀錄已經被移除 但是M-View的資料還是一樣的,如下圖 這時如果我們下了REFRESH的話:

1
REFRESH MATERIALIZED VIEW spree_products_mview;

M-View的資料就會和資料表上一樣了

以上是簡介Materizlied View在PostgreSQL的作用,接下來我們還會針對如何用Rails / ActiveRecord操作這個功能作出說明。

2013回顧[CH]

| Comments

2013大事紀

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

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

加油!

Rails Girls Taipei-01 活動主辦心得

| Comments

Group photo of Rails Girls Taipei-01

以下是我和高見龍 以及泰安 共同主辦第一屆Rails Girls Taipei活動的心得

Rails Girls社群

有關於Rails Girls社群的介紹可以參考Open FoundryInside的介紹, 在此就不再儹述。

緣起

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

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

在日本的見聞

我在五月底至六月初和高見龍一同前往日本參加Rubykaigi 2013時, 有幸和日本Rails Girls的主辦人柴田博志先生討論了如何教不會程式的女生上手Rails的方式, 他講到了一個重點「藉由copy & paste, 讓學員有成就感」。

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

Photo with Nakawaza and Yamaneko @Rubykaigi2013 (在RubyKaigi會場和Rails Girls的學員中澤(中)以及知名的mrubyist Yamane(右)合照)

開始籌辦

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

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

Rails Girls Taiwan Logo

贊助商

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

場地

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

Rails Girls Taipei-01 Venue

報名

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

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

選取標準

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

  1. 為什麼妳想參加這個活動?
  2. 讓我們了解妳是一個怎樣的人?

事前準備

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

現場狀況

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

現場1 現場2

After Party

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

Rails Girls Taipei After Party 2 Rails Girls Taipei After Party 3 Rails Girls Taipei After Party

感想

Ruby真的是一門神奇的語言啊, 原本只是基於想要改變社群性別分布不均這個現狀的心情, 從國外引進並舉辦了這個活動, 卻得到了遠遠出乎意料的反應與成果, 看來21世紀的程式學習趨勢真的不是說說而已, 今後也會繼續這個活動下去, 感謝活動過程中一路相挺的朋友們, 謝謝大家。

How to Migrate a PostgreSQL DB With Many Schemas in a Multenancy Rails Application

| Comments

PostgreSQL的schema是一個非常方便的功能, 適合拿來做所謂的Multi-Tenancy類服務; 例如無名或Pixnet這類的BSP(Blog Service Provider)或是像我的FREEBBS的免費論壇服務(Forum Service Provider), 通常稱為SAAS(Software As A Service)系統, 可以把N個相同結構的schema放在同一個資料庫裡面; 比起MySQL只能分別放在不同的資料庫裡會有很多好處。

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

  • 管理用schema(只有一個)
  • Blog Schema(有無數個, 每個的結構相同)

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

database.yml
1
2
3
4
5
6
development:
  adapter: postgresql
  encoding: unicode
  database: SHOPON_development
  pool: 5
  schema_search_path: base, blog1

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

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

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

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

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

  1. 在migrate檔內設定只能在服務端schema或是管理端schema執行
  2. 單獨migrate管理端單獨migrate服務端的功能

實現1.的方式如下

migrate_control_side.rb
1
2
3
4
5
6
7
8
9
10
11
class CreateSites < ActiveRecord::Migration
  def change
    if ActiveRecord::Base.connection.schema_search_path == 'base' #base為管理端schema
      create_table :sites do |t|
        t.string :subdn
        t.string :name
        t.timestamps
      end
    end
  end
end

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

multitenancy_migration.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module ActiveRecord::MultitenancyMigration
  def must_migrate_in_base #管理端
    if ActiveRecord::Base.connection.schema_search_path == 'base'
      yield
    end
  end

  def must_migrate_in_site #服務端
    schema_search_path = ActiveRecord::Base.connection.schema_search_path
    if !schema_search_path.index('base') && !schema_search_path.index('public')
      yield
    end
  end
end

ActiveRecord::Migration.class_eval do
  include ActiveRecord::MultitenancyMigration
  extend ActiveRecord::MultitenancyMigration
end

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

實現2.的方式如下

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

base.rake
1
2
3
4
5
6
7
8
9
10
11
12
namespace :base do
  task migrate_db: :environment do
    ActiveRecord::Base.connection.schema_search_path = 'base'
    Rake::Task['db:migrate'].invoke
  end

  task rollback_db: :environment do
    ActiveRecord::Base.connection.schema_search_path = 'base'
    Rake::Task['db:rollback'].invoke
  end

end
site.rake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace :site do

  def check_subdn_exists
    if ENV.has_key?('SUBDN')
      ActiveRecord::Base.connection.schema_search_path = ENV['SUBDN']
      yield
    else
      puts "Please assign SUBDN first!"
    end
  end


  desc 'Migrate Database of Individual site, have to assign SUBDN paramater!'
  task migrate_db: :environment do
    check_subdn_exists do
      Rake::Task['db:migrate'].invoke
    end
  end

  desc 'Rollback migration of single site'
  task rollback_db: :environment do
    check_subdn_exists do
      Rake::Task['db:rollback'].invoke
    end
  end

end

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

以上

Introduce Ruby Taiwan Community@RubyKaigi 2013[EN,CH]

| Comments

非常榮幸本次有機會可以和台灣Ruby社群的朋友一起參加世界級的Ruby研討會RubyKaigi2013, 做為台灣Ruby社群的主持人之一, 既然參加了就想要讓世界的Ruby朋友們知道Ruby Taiwan社群的存在, 因此在LT徵稿前就打算要投稿這個主題了.


It’s my pleasure to join the world-class Ruby seminar RubyKaigi2013, 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.

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


Since this is my first time to speak outside of Taiwan and it’s a 5 mins LT session, I decided to use the Takahashi-method on my talk. I watch Takahashi-san’s slide and screencasts again and again to meditate and practice my speech. Special thanks to @ihower’s opening slide at RubyConf Taiwan 2012 and @hsbt’s Japanese translation on Rubyist Magazine 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 David Hou 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: “We should be more careful, you represent the Ruby Taiwan community after all” when I expressed my thank to him. He really moved me!

另外一個最後引起日本朋友們關注的就是桐島梗了, 其實會有這個梗是因為自從去年Rubyconf Taiwan 2012後就有在關注日本Ruby大神們的推特, 適逢今年3月時日本舉辦的大江戶RubyKaigi03其中一場由CRuby GC的作者中村成洋@nari3的演講桐島、Rubyやめるってよ持續引起大神們的討論, 看了簡報之後雖然不是很懂但是對其中引用的電影聽說桐島退社了感到興趣, 看過之後再回頭看中村的簡報就能夠理解那些梗了, 個人以為那句「戰鬥吧!這裡是我們的世界」是整個電影, 同時也是我自己參與社群經營活動的精神之體現, 作為結尾是非常適合的.


I found the most eye-catching point of my presentation for Japanese is the 「Kirishima」’s ネタ. In fact I started to follow many Japanese Rubyist’s twitter after the RubyConf Taiwan 2012 last year. I noticed Narihiro Nakamura’s presentation named 「Kirishima, stop using Ruby」 which is retwteed many times after the 「Oedo RubyKaigi 03」 on March this year. I am extremely interested by the slide’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 “Fighting, this is our world!” 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.

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


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

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


It was a miracle that on the third day of RubyKaigi2013, my slide was in the 「Hot in Facebook」 area of Slideshare’s homepage.

感謝高井先生的照片, 拍的非常好.


Thanks to the high quality photo taken by Naoto Takai.

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


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.

Thanks to all awesome staffs of Rubykaigi and community friends in Japan, また台湾で会お!

附上簡報檔以及當天Live如下:


Video streaming by Ustream

達人出版会徵求翻譯以及校稿志工事宜

| Comments

大家好:

達人出版会是由日本知名Rubyist, 也是高橋流簡報術的作者「高橋征義」成立, 目的是透過實踐「敏捷出版」的方式出版技術系的日文純電子書籍, 這邊有一份非常詳盡的介紹文章

最早知道這個網站是在RubyConf Taiwan 2012高橋的LT時提及的

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

譯者

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

校稿志工

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

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

下面是目前我覺得比較有特色可以翻譯的書籍:

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

目前(5/3)為止的募集情況: 校稿志工x3(包括我), 從開始募集譯者一天竟然已經超過10位, 由於報名情形遠超乎想像, 因此之後將請報名者至此填寫基本資料後再試翻作為參考, 謝謝大家!