What have you found for these years?

2008-10-09

merb (2)

我可以很認真地這樣說了,等 merb 1.0 出來後,rails 我就要丟到馬桶裡了。
還沒試完,東西只改寫了一半。其中碰到最大的困難是,partial 我試很久才找到方法。
因為網路上的 tutorial 往往都是過期的 @_@b

先講缺點好了,因為這很明顯。

1. 文件不足,很多教學都過期了,規格有改。這部份我大概都是看 yard doc
和推測可能寫法。光這樣就把大部份的寫法猜對了,還算不錯。但文件不足還是問題。
不過我相信等 user base 大了後,這部份就會好很多了。

2. 有一點小 bug, 還有部份容錯能力不足。比方說 form_for 丟個 nil 進去,
就會吐出很詭異的錯誤。如果沒一路追蹤到 source code 的話,看不出來到底錯在哪...
這部份 rails 給的提示比 merb 多很多,雖然還是有所不足。

以上是目前試到幾個不便之處,但相信這等 1.0 推出後都會好很多 ~~

優點呢?

1. development 下 route 會自動重讀,重讀狀況良好。rails 這邊有時候
會怪怪的,所以我常常變成乾脆一直重啟 server... 當然啦,現在還沒試到複雜的東西,
merb 在這邊沒出狀況也是應該的。

2. log 訊息非常充足。讀取哪個 env, 讀取哪個 init,
讀取哪個 gem, 等等資訊非常清楚。merb -i 時,用 data mapper 存取
database, 也會自動印出產生出的 sql! 不像 rails 還要動點手腳。

此外,rails 在 thin/mongrel 下 log 輸出有微小差異,例如 thin
好像都會輸出到檔案,但是 mongrel 在沒有 daemonize 的情況下,
會輸出到 stdout. merb 在此完全統一處理,不同 server 差異就減少了。

3. merb 啟動速度應該是 rails 好幾倍吧 @@ rails 我都要等一下,
merb 按下去就啟動完畢。不過預設就跑 master + worker,
光這樣的話是比 rails 吃記憶體... 但如果 master + worker 就可以抵掉
rails 2 process 的話,那就反而是比較省記憶體了!

4. no more strange magic! 由於 rails 的 named routes 是用如:
formatted_user_path 或 user_url, etc. 導致要 wrap 一層變得很麻煩。
可能變成?

def my_path(name, type); eval("#{name}_#{type}"); end

這樣很討厭啊!所以我乾脆不包了,直接在每一個地方重複呼叫:

formatted_user_path(*with_format(user))

可是這樣真的很煩啊!merb 是這樣做的:

Merb::Router.url(:user, :user => user)

大概啦,我還沒試到這麼複雜的情況。簡單地說,沒有奇怪 generated method 了。
當然更加不用 method missing... 這東西用多了真的太容易生出奇怪的 bug.
總之,router 就是 router, 所有的東西都應該乖乖地歸類在他該有的 module 下。
而不是像 rails 那樣全部都混在一起,用起來很方便,想想卻是一團混亂...

現在想到最讓我不滿的,是他的各種 helper, 很多都卡死在一起,沒辦法簡單地
重複利用,需要自己找到 dependency, 不然就是想辦法弄出一個 ActionView::Base

我有因為一些問題而去翻 merb-helpers 的 source code, 裡面程式也很乾淨...
rails 還有一點很可怕,就是一個 class 會在好多地方定義不同的 method.
你要找某個 class 有哪些東西,還要看一堆檔案.... 還四散各處哩。

不過其實仔細想想,merb 這樣才是該有的水準吧?以往看 C++ 程式大多也都很漂亮。
(ㄟ,我是說 boost, Loki, blitz++, Qt 等等名作...)

5. 跟 data mapper 整合得非常好。use_orm :datamapper 之後,
rake task 自動追加該有的 task. 除了 rails 傳統的 migration 外,
還有 "crazy" migration, 其實就是整個抹掉重建啦。
最重要的是有 autoupgrade!


> bin/rake dm:db:autoupgrade
(in /Users/godfat/projects/gits/rkc/merb)
Loading init file from /Users/godfat/projects/gits/rkc/merb/config/init.rb
Loading /Users/godfat/projects/gits/rkc/merb/config/environments/development.rb
~ Loaded DEVELOPMENT Environment...
~ loading gem 'merb-helpers' ...
~ loading gem 'dm-validations' ...
~ loading gem 'merb_datamapper' ...
~ loading gem 'dm-core' ...
Loading init file from /Users/godfat/projects/gits/rkc/merb/config/init.rb
Loading /Users/godfat/projects/gits/rkc/merb/config/environments/development.rb
~ Loaded DEVELOPMENT Environment...
~ loading gem 'merb-helpers' ...
~ loading gem 'dm-validations' ...
~ loading gem 'merb_datamapper' ...
~ loading gem 'dm-core' ...
~ Merb::Orms::DataMapper::Connect block.
~ Connecting to database...
~ Checking if we need to use DataMapper sessions
~ Merb::Orms::DataMapper::Connect complete
~ Parent pid: 8028
~ Merb::Orms::DataMapper::Associations block.
~ Merb::Orms::DataMapper::Associations complete
~ Compiling routes...
~ PRAGMA table_info('messages')
~ PRAGMA table_info('messages')
~ PRAGMA table_info('messages')
~ PRAGMA table_info('messages')
~ PRAGMA table_info('messages')
~ PRAGMA table_info('messages')
~ PRAGMA table_info('messages')
~ SELECT sqlite_version(*)
~ ALTER TABLE "messages" ADD COLUMN "created_at" TIMESTAMP


自動偵測並改變 table 啊 ~~~ 這對於開發來說超方便的。
以往我在 rails 的作法,就是修改 migration, 然後整個抹掉重建。

> rake db:migrate VERSION=0
> rake db:migrate

之類的。記得有 db:reset 還是 db:migrate:redo 之類的,
搞不太清楚其間的差異 @@ 反正就是整個抹掉重建就是了。
需要 fixtures 就再讀進來即可。

> rake db:fixtures:load

不過有 autoupgrade 的話,又可以省掉這些麻煩了。

7. partial 內建迴圈 XD
(updated: 感謝 contagion 說明,rails 也有相似功能)
Rendering a collection of partials

partial :message, :with => @messages

這樣等同於 rails 的:

@messages.each{ |message|
  render :partial => 'message', :locals => {:message => message}
}

8. layout 應該可以 nested, 不過我還沒試到,因為目前用不到。
應該是依靠 ooo_content 系列,還有跟 rails 不一樣的 erb 語法:

<%= form_for ... %>
喔哈哈
<% end =%>

注意多了兩個 =, 能做到 nested layout 應該跟這有關。
此外也能使用 haml 等 template engine, 不過我懶得試了,
先要能讓 erb 能動。(不過他內部可能是呼叫 erubis, 這是 dependency 之一)


*


先講到這,搞太晚了,頭好昏... 不過看到 merb 這麼強,
不自覺就覺得有些興奮 XD 可能也像當初看到 rails 那樣有趣吧 :p
老實講,乖乖用 rails 提供的功能,不要想擴充的話,倒是好好的...
怪不得 merb 有一個說法是什麼 web framework(or rails?) for hacker 之類的。
雖然說在還沒真的試過 merb 時覺得 rails clone 有啥意思?
但感覺像是把 rails 的不好拿掉,好的留下來 :D

另一方面,其實兩者最大的差異,終歸一句話,
就是 rails 倚靠 magic, 而 merb 沒有那些 magic.
一個很熟 ruby 的人,看到 rails 的用法,可以想像到無數的可能實作。
但是看到 merb 的用法,就可以直接聯想到幾個最好的作法。

我相信最大的差異就在這。於是,merb 的門檻又比 rails 高很多。
尤其 merb-core 的東西很少,真的要弄到 rails 同等功能,
還要額外灌很多東西,也要記得把他們啟動起來。

只是,merb 原名是 mongrel + erb, 現在已經完全不是那麼回事了... XD
我當初看到的時候,還像在寫 mongrel 的 handler 耶...
沒想到轉眼就演化成 rails clone...

2 retries:

contagion said...

我也覺得 merb 才是 ruby 的 de facto web framework 該長的樣子。

Rails 就像 Visual Basic 一樣,方便是方便,可是要想偏離一下 ,就要翻一堆看不懂的 code,應付一堆莫名其妙的問題。不過現在 visual Basic 還是一堆人在用,相信 Rails 也會活繼續活很久的。

另外關於第七點,其實 rails 也有相同的功能
請參考
http://api.rubyonrails.org/classes/ActionView/Partials.html

Rendering a collection of partials
這一段

godfat 真常 said...

哈哈,一針見血 :p
Visual Basic 的形容不錯。
雖然我也看到有人說,Rails 會變得像 Smalltalk 一樣,
一直都只是那群小眾在玩。

不過我總覺得,只要在 Rails 裡照著他設計走,
完全不擴充什麼東西的話,應該沒有那麼難才對...
所以覺得 Visual Basic 的形容比較恰當 :p

另一方面,其實 Visual Basic 也算是 lang + framework (+IDE) 吧?

*

partial 的部份感謝 XDDD
這樣我可以回頭去把那些迴圈都修掉了 :p

Post a Comment

All texts are licensed under CC Attribution 3.0