顯示具有 RoR 標籤的文章。 顯示所有文章
顯示具有 RoR 標籤的文章。 顯示所有文章

星期五, 6月 19, 2009

OOPS?! rdiscount is not working on Windows

雖然我所使用的NB是Windows, 但因為我一直是連上server side (Ubuntu)去安裝系統與修改程式, 我的NB上並沒有開發RoR的環境, 因此一直沒發現這個問題, 一直到我們家的工程師試圖要在他的電腦上安裝測試環境才發現這個問題: rdiscount這個gem裝不起來!!!

他把這情況跟我回報, 我本來一直以為是他沒設定好或是有gem安裝順序造成的相依性問題, 但在我試圖幫他安裝卻還是一直出現錯誤, 後來努力一陣搜尋之後才發現:

rdiscount不能在Windows平台上運作?!?!

沒錯... 只要你拿到的程式有使用到這個gem, 那就暫時不要想能在Windows上執行了

細節可以參考下列的討論[1] [2] [3], 最無言的是有人問說rdiscount on Windows不work怎麼辦? 其中一個很OOXX的回覆是 rdiscount 只能在Mac and GNU/Linux systems運作喔, Windows請找替代方案...

那ridscount又是甚麼呢? ridscount是Markdown的一種實作, 簡單來說, 就是讓你想輸出在web page的文字 轉換成不會造成HTML crash的字元的一個小程式.

感覺RoR就是一個Windows不friendly的東西, 我不愛Windows, 但是這種平台支援程度我覺得算是很基本的. 系統環境以Windows為主的公司要使用RoR可千萬要三思. 我想rdiscount應該不會是不支援的唯一特例.

目前我所看到的RoR developers都是使用Mac Book, 且Ruby從TIOBE上看來與Mac OS X的成長正相關, 使用族群的特性也許該特別注意一下囉!

星期一, 6月 15, 2009

RoR中時區處理的問題

問題一開始是出現在一段很簡單也很常需要使用的程式碼, 程式希望撈出該年月所含括的資料. 資料庫裡面存的時間時區是UTC.

我們原先從vendor得到的程式碼如下, 但是運作一直不是很正常, 撈出來的資料總是有問題, 但vendor卻始終認為該程式碼沒有錯誤.

date1 = Date.new(year, month, 1)
date2 = Date.new(year, month, -1)
self.find(:all, :conditions => ["start_at >= ? and start_at <= ?", date1.beginning_of_day, date2.end_of_day] )

要求fix bug未果, 不得以只好自己動手, 台灣的時區是UTC+8, 因此當我們想要撈出所有台灣時區2009/6的資料時, 所需要下的SQL stmt其實是 2009-06-01 00:00:00+0800與2009-06-30 23:59:59+0800等同於2009-05-31 16:00:00+0000與2009-06-30 15:59:59+0000不幸的是, 上面這段程式碼並無法正常的運作.


>> puts Time.zone
>> puts date1.beginning_of_day.zone
>> puts date1.beginning_of_day
>> puts date1.beginning_of_day.to_s(:db)
>> puts date1.beginning_of_day.in_time_zone(Time.zone).zone
>> puts date1.beginning_of_day.in_time_zone(Time.zone)
>> puts date1.beginning_of_day.in_time_zone(Time.zone).to_s(:db)
>> puts Date.parse("2009-6-01T00:00:00+00:00").beginning_of_day.in_time_zone(Time.zone).strftime("%Y-%m-%d %H:%M:%S")


=> (GMT+08:00) Taipei
=> CST
=> 2009/06/01 12:00 AM
=> 2009-06-01 00:00:00
=> CST
=> 2009/06/01 12:00 AM
=> 2009-05-31 16:00:00
=> 2009-06-01 00:00:00

=> (GMT+10:00) Hobart
=> CST
=> 2009/06/01 12:00 AM
=> 2009-06-01 00:00:00
=> EST
=> 2009/06/01 2:00 AM
=> 2009-05-31 16:00:00
=> 2009-06-01 02:00:00

=> (GMT+00:00) UTC
=> CST
=> 2009/06/01 12:00 AM
=> 2009-06-01 00:00:00
=> UTC
=> 2009/05/31 4:00 PM
=> 2009-05-31 16:00:00
=> 2009-05-31 16:00:00

=> (GMT-10:00) Hawaii
=> CST
=> 2009/06/01 12:00 AM
=> 2009-06-01 00:00:00
=> HST
=> 2009/05/31 6:00 AM
=> 2009-05-31 16:00:00
=> 2009-05-31 06:00:00

剛看到Taipei部分的結果, 還以為使用date1.beginning_of_day.in_time_zone(Time.zone).to_s(:db)這段是可以正常運作的, 但是多測了幾個時區之後, 發現還是有問題, 無論設定任何時區, 永遠都得到2009-05-31 16:00:00這樣的值

而唯一會變動的兩個值是date1.beginning_of_day.in_time_zone(Time.zone)和Date.parse("2009-6-01T00:00:00+00:00").beginning_of_day.in_time_zone(Time.zone).strftime("%Y-%m-%d %H:%M:%S"), 但很奇怪的是, 這兩個數值變動的基礎都是先減8小時之後再計算與台灣地區的時差, 即使第二段程式是直接提供一個"2009-6-01T00:00:00+00:00"的時間, 希望能得到一個UTC時間之後再作計算, 但結果依然是失敗的.

後來在網路上好一陣搜尋之後, 才赫然發現這是個bug (or issue?)
https://rails.lighthouseapp.com/projects/8994/tickets/2479-inconsistant-time-zone-handling

文中的例子如下, 可以看出Date有時區處理的問題:


>> Date.today.beginning_of_day
=> Fri Apr 10 00:00:00 -0500 2009
>> Time.zone.now.beginning_of_day
=> Fri, 10 Apr 2009 00:00:00 CDT -05:00
>> Date.today.beginning_of_day == Time.zone.now.beginning_of_day
=> true

>> Person.all :conditions => [ "created_at > ?", Date.today.beginning_of_day ]
=> Generated SQL => SELECT * FROM "people" WHERE (created_at > '2009-04-10 00:00:00')

>> Person.all :conditions => [ "created_at > ?", Time.zone.now.beginning_of_day ]
=> Generated SQL => SELECT * FROM "people" WHERE (created_at > '2009-04-10 05:00:00')


簡單說就是要用Time來取得的時間才會是你要的, 因此將原先的程式修改為下面這樣就搞定啦!


fmTime = Time.zone.local(year, month, 1, 0, 0, 0)
toTime = Time.zone.local(year, month, -1, 23, 59 ,59)
self.find(:all, :conditions => ["start_at >= ? and start_at <= ?", fmTime, toTime] )

>> puts Time.zone
>> puts fmTime.to_s(:db)
>> puts toTime.to_s(:db)


=> (GMT+08:00) Taipei
=> 2009-05-31 16:00:00
=> 2009-06-30 15:59:59

=> (GMT+00:00) UTC
=> 2009-06-01 00:00:00
=> 2009-06-30 23:59:59

=> (GMT-10:00) Hawaii
=> 2009-06-01 10:00:00
=> 2009-07-01 09:59:59

如此終於搞定一個邏輯上很簡單處理的bug... RoR還是讓我很無言...

星期五, 6月 05, 2009

RoR的restful_authentication plugin在IE 8上的問題


今天網站在作測試時, 有人反映IE 8無法正確的導到login畫面, 而會跳出這個畫面, 找到原因是因為IE 8有時會送出空的HTML Accept header而使得程式跑到format.any這個區塊, 因此會造成跟其他瀏覽器不一樣的情況.

一個簡單的修改方法是將lib/authenticated_system.rb中原本這段
def access_denied
respond_to do |format|
format.html do
store_location
redirect_to new_session_path
end
format.any do
request_http_basic_authentication 'Web Password'
end
end
end

改為下面這樣, 因為我們暫時沒有其他的format, 所以使用format.any來作判斷
 def access_denied
respond_to do |format|
format.any do
store_location
redirect_to new_session_path
end
end
end
這樣就可以正確的進入login畫面囉.