我的網誌已搬家至blog.miaout17.net,本網誌將不再更新

2010年10月18日 星期一

Rails 3練習筆記

這幾天有空時,把rails 3的東西練了一下。基本上我是照著xdite的這篇練習中,rails部份的七個步驟做一遍。雖然xdite在寫這篇時用的應該還是rails 2.x,但要練的概念應該大同小異吧。我手上的參考書是AWDR2(是的,是第二版),和Beginning Rails 3(買來後發覺有點太淺了,但對於與rails脫節太久的我來說,還是不錯的參考書)。如果要玩rails 3的,要查東西似乎還是先查Rails Guide比較快 -- 因為Rails 3太新了,直接Google很常會搜到舊版本的solution。

以下是我印像較深的問題筆記,內容包括把xdite的練習跑一遍,並試著deploy到Heroku和自己的Linux Server上…

安裝ruby + rails development環境…我使用的OS是Ubuntu。一開始沒看到xdite這篇的說明,很白目的用了apt-get install ruby。結果就踩中了ruby 1.9.1 + rails 3.0.0當機的雷(rails 3現在官方只支援ruby 1.8.7及1.9.2)。我想不只是這個原因,用套件的ruby還會有很多相依性的問題吧。最後我因為想同時試rubby 1.9.2和1.8.7,所以選用了rvm,就算沒有要切版本,感覺用rvm管理ruby也滿乾淨的。

gem install rails不知為何速度超慢,而且console完全沒有回應。改用gem i --verbose rails,才能確認真的有在跑,沒有當機。
( 3)論壇的文章要能夠分頁,每一頁 20 筆,每一個論壇要秀出現在論壇裡有多少 post 數量。可用 params 配合 named_scope 在文章列表排序。
一開始我寫好了counter cache,在「看版列表」中成功的使用了counter cache減少select count query。接下來做paginate時,一開始我看別人的範例寫成這樣(省略無關的condition)

Article.paginate :per_page => 20, :page => params[:page]

但在server console中發現還是有select count的query,trace了一下will_paginate源碼,發現雖然will_paginate沒有正確讀到cached count,但可以在paginate時當參數塞進去:

Article.paginate :per_page => 20, :page => params[:page], :total_entries => @forum.articles_count,

當然,最後才發現rdoc根本有寫可以這樣下參數 Orz
( 4)每篇文章可以上傳附件
雖然可以用paperclip plugin,但這功能我選擇試著手刻看看。我在開發過程中有丟上Heroku,然後才想到「啊...Heroku沒辦法寫入靜態檔案,要的話要用S3」。
( 5)Admin 可以刪改所有文章,建立一個後台做這件事。網址是 http://example.org/admin/。只有身分是 admin 的人可以進後台。admin 的判別方是 column 裡加一個 boolean,判斷是否 admin。這個 attribute 必須用 attr_accessible / attr_protected 保護。
Admin namespace我是照這篇做的,做了看版管理及文章管理。就一般論壇而言,像「看版管理」這種東西,一般人不會有新增、修改、刪除的權限(版主可能有修改),所以scaffold架出來的東西應該的確比較適合移到admin去,而給使用者的邏輯再手動打造。但我的實作有種不夠DRY的感覺,把view和controller的code複置兩份,感覺不太好。可以想見,其實可以利用繼承、共用函式等方式,將程式碼變的更精簡。這部份有更好的best practice嗎?
( 6)用 Rake 撰寫自動化步驟,生假資料。寫一個 rake 可以達成以下步驟:「砍 db => 建 db => 跑 migration => 生種子資料」,另一個 rake 是生假文章與假論壇。
heroku不給直接跑rake db:drop。也就是說不能heroku rake db:drop,但可以heroku db:reset; heroku rake dev:fake。當然,這應該也可以寫成一個local的task。
( 7)在租來的 VPS 上面建置 Ruby on Rails production 環境,使用 Ruby Enterprise 與 mod_rails。使用 capistrano 佈署 application。
首先,我選用的VPS是linode。之前因為好奇,租過一個月的linode來玩,所以就選擇了這個較熟析的環境。灌了linode提供的Debian image後,接下來照著xdite建議的rails-nginx-passenger-ubuntu這篇做。一路上沒碰到什麼問題。

接下來,聞capistrano之名已久,但不知為何這個ruby上最有名的deploy工具,文件似乎有點少。Anyway,看著AWDR2和一些網上的教學,還是可以做的出來。我一開始照著網路上的一些文件,把deploy時的symbolic link功能做好。但bundle gems的問題我一時找不到best practice…看了這個影片,雖然覺得解法好像不夠好,但還是先照著做了。bundle path找不到的問題,除了在run中打absolute path外,也可以在deploy.rb中下

default_environment["PATH"] = "/opt/ruby/bin:/usr/bin:/bin:/usr/sbin:/sbin"

去指定path。

最後我的deploy.rb大概致上如這個gist。但我對capistrano的best practice仍有許多疑問…bundle install要自動化嗎?如果不自動化,在機器很多時要一台一台bundle install?自動化的話,要讓capistrano use_sudo嗎?不sudo的話,gems要裝在vendor/gems嗎?如果這樣做的話,vendor/gems要不要做symbolic link呢?(像我現在每cap deploy一次,就把所有系統沒有的bundle gems裝一次,其實有點慢)。

目前練習到這邊。基本上要跑完這份練習沒有難度,但很多地方會覺得處理的不夠好。Best practice可能需要看書或資料、有人指導、或經驗的累積吧…

2010年10月4日 星期一

再度考慮搬家

最近應該比較有閒寫心得了,又開始考慮搬Blog的可能性。其實一年前就murmur過這件事了。如果要搬的話,應該就是搬到自己架的Wordpress吧。主要的原因還是這些:
  • 貼code:Bloggger貼code縮排好像還是有機會跑掉。我真的不喜歡一天倒晚embed gist,然後python&haskell縮排跑掉真的很杯具。另外是Wordpress有儲存文章revision的功能,code不小心貼爛還可以回退,而Blogger就沒招了,只能從原本的code從貼一次。
  • 貼數學式:雖然有好幾個方法可以在Blogger上貼數學式(先自己用tex轉圖、用Google Graph API...),可是我都嫌不太方便。我還是較喜歡直接在文章中打類似tex的控製碼。Wordpress有一些plugin可以做到這一點。MathML是一個理想的解法,但目前只有Firefox有較完整的支援,而在Chrome慘不忍睹。
有人有什麼好建議嗎?

2010年9月19日 星期日

OpenFoundry疑似烏龍事件?

今天無意間發現中研院OpenFoundry有一篇文章,作者名稱是我的「本名」,但該篇文章並不是我發的。事實上,我的姓氏及名字都不是很常見,google一下大概我的本名,大概可以猜測台灣地區華人並沒有與我同名同姓的人。

中午才看完「盜圖者,剛剛賠了我十一萬」這篇文章,遇到這個狀況真怕有人誤會我盜文。為求自我保護,我立即去信OpenFoundry反應此事,在此公佈我的信件內容。因為該文上還有我的個人資料,故涉及該文及我的個資的部份,我會消音處理:
您好:

今天在瀏覽OpenFoundry網站時
無意間發現了一篇文章:「AAAAAAA」
(該文網址: OOOOOOOOOOOO )
作者姓名竟然與我的名字相同,但本人並未在貴站發表該篇文章。

原懷疑為同名同姓,但本人姓名相當罕見
資訊領域有人與我同名同姓的機率應相當低。
另外,以該文標題至Google搜尋
竟然發現BBBBBB索引網站收錄該文時,附帶著我的真實姓名及E-Mail
(目前在此網址可以看到:OOOOOOOOOOO )

因此,本人懷疑此次事件為OpenFoundry網站問題,造成我的個人資料外洩
若真的是這樣的問題,我想要麻煩貴站站方做以下處理:
1.將我的名字從該篇文章中刪除
2.聯絡BBBBBB站方,將我被索引的個資刪除
3.釐清並解釋問題發生的原因,避免此問題再度發生

為避免有人懷疑我抄襲原作者的文章
基於自我保護,我會立即將本信部份內容公開於本人Blog上

期盼站方盡速處理此事

Best Regards,
XXX

2010年8月15日 星期日

Blogtrans更新

剛剛突然想到,之前Blogtrans有改一些code,但一直沒放出來。看了一下git log....2009/05/26(汗)。

順手打包了一下,上傳到sourceforce,雖然code是一年多前寫的(汗)

* 增加Blogger匯入功能
* 處理一些無名XML不是well-form的狀態,或者是出現UTF-8不合法的字元
* 增加UnitTest,順便修正了一些minor problem....

新版的程式一樣可以在Sourceforce抓到

2010年7月2日 星期五

[FLOLAC]心中有Monad,萬物皆Monad

1.打完之後才突然發現....我原本只是想打個輕鬆的心得文,怎麼搞的那麼嚴肅 Orz

2.竟然遇到小我X(消音)屆的高中+大學學弟,嚇然發現自己變老人了

3.我給了幾個人聯絡方式,可是後來才想到我沒拿任何人的聯絡方式。如果有同學看到歡迎回個文。

正文開始 Orz



星期二時,scm老師談到「今年FLOLAC中,Functional Programming的課比較少,選用的是OCaml而不是Haskell,不會討論Monad之類的東西」。有趣的是,我覺得「就Operation Semantics的角度,來討論imperative program的derivation」,這件事本身就有濃厚的FP味道存在。

首先,從最基本的<s1, s>->s'談起:給予一個statement S1及初始狀態s,會得到最終狀態s'。對於deterministic semantics,<s1, s>->s' and <s1, s>->s'' imply s'=s''。換句話說,如果將S1視為一個routine,給予相同的input,會得到相同的output,這不就是pure function的定義嗎?另外就像Josh Ko談過的:與其說FP沒有side-effect,不如說FP沒有implicit state。然而<s1, s>->s'這樣的表達法,也讓imperative language中的所有狀態變化被攤開來,使其在某些方面可以像FP一樣地分析。

接下來,舉出老師在課堂上給的兩個quiz:

* 原本derivation只做到statement的層次。如果要將arithmetic expression做derivation,其型別應該是什麼?(Ex. x = y + 5; )
* 如果語言中出現「具有side effect的arithmetic expression」,其derivation的型別是什麼? (Ex. x = ++y; )

假設算數運算的值域為整數,其中第一個應為<AExp, State> -> int。第二個應為<AExp, State> ->(int, State)。這個答案其實很直觀:前者只要求值,後者求值順便變更狀態。這不是跟State Monad中的一些型別很像嗎?
  • 語意為「修改狀態不求值」
    <Statement, State>->State
    execState :: State s a -> s -> s
  • 語意為「不改狀態只求值」
    <AExp, State> -> int
    evalState :: State s a -> s -> a
  • 語意為「又改狀態又求值」
    <AExp, State> ->(int, State)
    runState :: State s a -> s -> (a, s)

State Monad是pure functional language中可以模擬imperative language的關鍵,而Operational Semantics又以接近pure functional的方式去分析imperative language(在不涉及parallel與nondeterministic的情況下)。上OP的課時,我反而在心中印證了對於FP的認知。

2010年6月6日 星期日

2010-06 久違的Blog更新

十個月沒更新文章了,把最近的事摻在一起記一記:
  • 「大鳥共和國」改名為「大貓共和國」(Kero?)
  • 看了龍紋身的女孩(?)
  • 參加了Google Code Jam 2010的比賽,在Round 2(3000名取前500名)被刷掉了
  • 今年終於跟公司請了十天的假,去參FLOLAC 2010的課程

看完了龍紋身的女孩三部曲,讓我熱血(?)的研究了一陣子破解技術
雖然目前還只是基礎Wargame都可能卡關的肉腳程度啦

我大概還滿嚮往「在資訊領域中極度自由」的感覺的
不管是「在Open Source的世界中,想要什麼都可以自己來」
或是「在資訊安全的領域中,如入無人之境」

不過這種「想要什麼,信手拈來」的自由,先決條件是在該領域各方面都很強吧...

GCJ打到前3000名不是什麼太好看的成積
沒啥好說的,就是基礎功不夠強吧...

一直以來我都用這樣的理由說服自己
「對於這方面競賽的能力不夠強,
 只是我沒針對Online Judge比賽需要的能力(演算法、解題速度等)做特訓,
 而把學習重心放在程式語言、API設計等等,需要架構高階複雜邏輯的地方」

其實這根本是藉口藉口藉口藉口藉口
在比賽中,基本功的不足之處,會一一無所遁形的暴露出來
演算法、離散數學、機率統計(這個比較少,但寫練習時有一題是要用機率的)
甚至資料結構的規劃也有問題,有時code寫到一半才發現結構redundant & stupid

從大學、研究所、工作,常常聽到
「這些東西還好啦,除非你從事演算法或學術相關工作,否則用不太到」這樣的說詞
真的是這樣嗎?我想不是的
這些基本功的強度會直接影響思考邏輯、工作速度、程式碼品質

依我前陣的子的個性,可能是不會把這段寫出來的
(因為過個一兩年,回頭看自己的文章時會覺得「啊啊啊,當時的自己又弱又愛胡說八道」)
但依我懶惰的個性,搞不好過一陣子就忘了這件事,一年後還是沒有針對基本功做加強
寫下來給自己當的目標吧,目標GCJ 2011前25名,加油!


最後,關於FLOLAC 2010
自我一兩年前對Functional Programming産生興趣起,就一直對這個課程有興趣
今年終於向公司請假去參加了,大概也會遇到一些收看此Blog的網友吧 :)

2009年8月21日 星期五

用git管理具有external的svn repository

睡不著爬起來寫blog,明天要早起的說 Orz



git是一套目前非常流行的分散式版本控制系統
相信很多人和我一樣,熟析git後就不會想用svn或cvs來管理源碼

我最近碰到這樣的問題:
專案主要使用svn做版本控制,但是我個人想用git管理
大家第一個想到的應該是git-svn
但git-svn對於svn external的支援並不完善

然而我目前的專案大量的使用了svn:external

src/
src/A => external to another project
src/B => external to another project
src/C => external to another project

更糟的是,因為專案開發時間的因素
A,B,C專案與主專案是共同開發的
有的時候我必需修改external library的API,並commit回去
有時其他人修改了external library,主專案必需跟著修改
(I know it doesn't sound good, but it's real world problem...)

我試過不管是單純的使用git-svn,或者借助一些shell script
都無法順利的處理這個工作流程

直到今天我想到一個實在是很瞎的方法:

mkdir gitrepo
cd gitrepo
git init
svn checkout svn://my-svn-repo-addr svnrepo
echo .svn > .gitignore
git add .
git commit
git chekcout -b svn-tracker

白話解釋一下:
在gitrepo/ 開一個git repository
在gitrepo/svnrepo 開一個svn repository
把.svn ignore掉 =.=
做一個名為svn-tracker的branch

這個看來愚蠢的方法 (對我目前的環境) 出手意料的好用
在改code時我都切換到其他branch (並且忘了svn的存在)
做任何svn操作時,我先切回svn-tracker branch

要做svn update的話就是
svn update
git add .
git commit -a

要commit自己的東西回svn mainstream就是
git merge work-branch
svn add *
svn commit

當然這些事可以寫shell script來完成



目前最大的缺點大概是沒法將git branch對應到svn branch (很麻煩)
不過還好我沒有很在乎....反正mainstream svn上沒有人在用branch & tag 功能,大家都只改trunk



這樣做還得到了意外的好處:
當要回退到舊版本時,如果沒有特別指定external的revision
就算update trunk to older revision,external還是會是最新版的
這樣會造成舊trunk + 新external,版本不相容的問題 (如果external行為或API有變)

上面的流程,每跑一次svn update
就等於把當時的情況做一次snapshot存進git
之後也就可以正確地回退版本....