在 Monorail 裡啟動 Logging 的方法

參考這篇:Enabling logging就行了。

整理如下:

  1. 在 public 下新增一個檔案 log4net.config:
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <log4net>
    <!-- Define some output appenders -->
    <appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net" >
    <param name="File" value="log.txt" />
    <param name="AppendToFile" value="true" />
    <param name="RollingStyle" value="Date" />
    <param name="DatePattern" value="yyyy.MM.dd" />
    <param name="StaticLogFileName" value="true" />
    <layout type="log4net.Layout.PatternLayout,log4net">
    <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] (%X{auth}) - %m%n" />
    </layout>
    </appender>
    <root>
    <!-- priority value can be set to ALL|INFO|WARN|ERROR -->
    <priority value="INFO" />
    <appender-ref ref="rollingFile" />
    </root>
    </log4net>
    </configuration>
    
  2. 在 public/web.config 裡面,註冊 service:
    <monorail>
    <services>
    <service
    id="Custom"
    interface="Castle.Core.Logging.ILoggerFactory, Castle.Core"
    type="Castle.Services.Logging.Log4netIntegration.Log4netFactory, Castle.Services.Logging.Log4netIntegration" />
    </services>
    <!--略...-->
    

電影流水帳(2008/1/1~2008/1/4)

  • 我們這一家電影版,典型的母女靈魂互換故事,給小朋友看還不錯。
  • Devil Wears Prada, The DVD: Meryl Streep, Anne Hathaway(IMDB, Wikipedia),與其說老闆苛刻,或許應該說這是現實吧。之所以好看,是因為赤裸的把真實搬上螢幕,不過人有選擇的權利啊,你可以不必要忍受,所以最後主角選擇離開。看完以後,你最應該要佩服的人是 Emily 跟她的老闆 – Miranda。
  • T4xi(IMDB, Wikipedia),沒有前幾集好看,這一系列在第三集開始走下坡,而這一集,第四集,沒有太多特效,搞笑情節居多。最喜歡裡面可愛的外公跟那兩個孫子,真快啊,第三集才剛出生,這一集裡面就已經長那麼大了。

Monorail ActiveRecord Scaffold

今天看官方文件時,看到這個:ActiveRecord Scaffold
只要有 model,monorail 可以自動幫你把 controller configure 成有 scaffold 功能 (CRUD都具備) 的 controller:

[Scaffolding( typeof(Blog) )]
public class BlogsController : Controller
{
}

這真是令人驚訝…不過 rc2 預設的 Layout 有問題,所以你最好加上 [Layout] attribute,自訂 Layout 比較好…
缺點是,要作 localization 的話,依照現在 rc2 的代碼,根本不可能…

結論是,有空可以來看看這邊的代碼(ARFormHelper.cs/PresentationHelper.cs),因為 Generator 裡面的 ScaffoldHelper 有些情況沒考慮的很仔細。

2007回顧(1)

去年像瘋了似的,看了 104 部電影,這裡面包含 DVD、第四台、嗯嗯的,平均起來,每週約兩部片子…
至於連續劇類(含影集、日劇)則是看了Prison break、醫龍、交響情人夢跟寶蓮燈,如果少看這些,應該可以省下更多時間來看更多電影…

第一次機車被拖吊

出門正要騎車載老婆去上班時,卻發現機車不見蹤影。
心想,該不會被拖走了吧。果不其然,老婆發現地上有寫下拖吊場的聯絡電話,於是…
計程車到拖吊場:NTD$180
拖吊場領車:移置費NTD$200、保管費NTD$300、在禁止臨時停車處所停車罰款NTD$600
機車平安無事…無價…

電影流水帳(2007/12/25~2007/12/31)

很拼命地看了三部片子,看到不錯的演員張靜初跟久違的桂倫鎂…

  • Bee Movie(IMDB),蜜蜂在人類法庭控訴人類盜取蜂蜜的官司故事,一開始起頭不俗,可惜後來還是脫離不了人類的思維。如果只是拿來跟小朋友介紹關於蜜蜂的一些事情還不錯。
  • 不能說的·秘密(IMDB),周杰倫自導自演的第一部電影,我自己覺得他拍的不錯,劇情流暢,氣氛也不錯,值得看看的電影。
  • 門徒(Wikipedia)。嚴格來說,並沒有真正全部都看完,從前面的三、四十分鐘切入,後面則脫漏了一些細節。描述警察為了查出整個毒網,派出臥底Nick,潛伏長達數年以查出所有細節,潛伏到最後甚至變成接班人。看得出來,導演與編劇有認真作過功課,所以對於吸毒、賣毒者的描寫非常真實。值得一看的電影。裡面張靜初與古天樂先後都提到一段屬於自己的故事:

    當初我認識他(她)的時候,他(她)就在吸毒了,後來在一起以後想勸他(她)戒掉,可是他(她)卻說不可能戒掉,於是我就陪他(她)吸,想證明可以戒掉,那知真的很難戒掉….

    ,再對照後面林昆(劉德華)講的一句話:

    那些癮君子最會裝,吊起癮來。有什麼做不出?有什麼說不出?千萬別招上這些人,不然你還以為自己做錯了。

    ,真的是很令人唏噓,毒,不能碰啊…

如何在 CentOS 安裝 Ruby on Rails

如果你照著這篇:在 CentOS 安裝 Ruby on Rails,卻怎麼樣也裝不起來的話,我想你碰到跟我一樣的問題了。錯誤訊息可能會是這樣子的:

ERROR: While executing gem … (Gem::GemNotFoundException)
Could not find rails (> 0) in any repository

研究了一下,發現應該是因為 RubyWorks 所提供的Source 沒有 rails gem 的關係,這也跟 RubyWorks 定位為 Production server 有關係。
總之如果你想把 CentOS 當作開發環境的話,不妨用

$sudo gem sources -a http://gems.rubyforge.org

把官方的 gem source 加進去,然後再輸入

$sudo gem install rails -y

即可。

點給老張的歌

今天騎車上班的時候,不知不覺哼到這兩首歌,發現跟好友老張的心境相符~
一首是野百合的春天

仿佛如同一場夢
我們如此短暫的相逢
你像一陣春風輕輕柔柔吹入我心中
而今何處是你往日的笑容
記憶中那樣熟悉的笑容
你可知道我愛你想你念你怨你深情永不變
難道你不曾回頭想想昨日的誓言
就算你留戀開放在水中嬌艷的水仙
別忘了寂寞的山谷的角落裡野百合也有春天

另一首是張震嶽作詞作曲的自由

我沒有關係 你可以假裝沒事離開這裡
一切好安靜 我只是想把情緒好好壓抑
到底誰會先說再見 我知道我一定哭泣
走的時候記得說愛我 愛我
說愛我 說愛我 難道你不再愛我
我的淚 滴下來 你從來不曾看過
為什麼 為什麼 愛情讓人變沈重
沒有人 告訴我 原來不是我想像
不要回來 你已經自由了 我也已經自由了

希望是不會走到這個地步:不要回來,你已經自由了,我也已經自由了。

How to monorail by Generator tool(4)

在研究過之後,我決定在 ScaffoldHelper.cs 裡面添加 GetText 這個函數,用來取得字串。

#region Localization helpers
public string GetText( IResource resource, string str )
{
if( resource==null )
return str;
object resStr = resource[ str ];
if( resStr==null )
return str;
return resStr.ToString();
}
#endregion

這樣在 .vm (template)檔案裡面,就可以這麼使用,以取得本地化後的字串:

$ScaffoldHelper.GetText($textres, "Name" )

當然你還是可以用原先的方法:

$textres.Name

所以 PageBrowser() 也可以跟著修正為:

#region Pagination helpers
public string PageBrowser( Page page )
{
return PageBrowser( page, null );
}
public string PageBrowser( Page page, IResource resource )
{
StringWriter output = new StringWriter();
PaginationHelper helper = new PaginationHelper();
helper.SetController(this.Controller);
string firstText = GetText( resource, "First" );
string prevText = GetText( resource, "Previous" );
string nextText = GetText( resource, "Next" );
string lastText = GetText( resource, "Last" );
if (page.HasFirst)
output.Write(helper.CreatePageLink(1, firstText ));
else
output.Write( firstText );
output.Write(" | ");
if (page.HasPrevious)
output.Write(helper.CreatePageLink(page.PreviousIndex, prevText ));
else
output.Write(prevText);
output.Write(" | ");
if (page.HasNext)
output.Write(helper.CreatePageLink(page.NextIndex, nextText ));
else
output.Write( nextText );
output.Write(" | ");
if (page.HasLast)
output.Write(helper.CreatePageLink(page.LastIndex, lastText ));
else
output.Write( lastText );
return output.ToString();
}
#endregion

最後在資源檔裡面加上必要的字串並且修改 .vm (template)以後,就可以得到本土化後的結果。

How to monorail by Generator tool(3)

這一次要講的是 Localization,不幸的是 Generator 沒有考慮到 Localization 問題,所以由 Generator 產生出來的代碼,並不包含這部份,但這卻是一個很好的機會讓我去了解 Generator 與 monorail 底下的機制。

Castle官方網站上已經有介紹該怎麼 Localization:Resources and Localization,但不幸的是,他使用 Visual Studio.Net 作為範例,Visual Studio.Net 已經掩蓋了所有細節。
在研究官方文件與相關文件之後,以下是我的步驟。

首先,你要先在 app/controllers 加上:

[Resource("textres", "ToDo.categories")]

這表示在 view(template) 那兒使用 $textres 就可以存取資源檔的內容。

所以在 app/views/categories/list.vm 裡,就可以把必要的字串改用$textres.字串名稱替代掉,這裡我就不列出整個 list.vm 了,只列出幾行:

<!--略-->
$HtmlHelper.LinkTo( $textres.AddNewCategory, "categories", "new")
<!--略-->
$HtmlHelper.LinkTo( $textres.View, "categories", "view", $category.Id)
<!--略-->
$HtmlHelper.LinkTo( $textres.Edit, "categories", "edit", $category.Id)
<!--略-->
$AjaxHelper.LinkToRemote( $textres.Delete, "delete.aspx", $DictHelper.CreateDict("with='id=$category.Id'", "condition=confirm('Delete?')", "onsuccess=new Effect.Fade('category$category.Id')"))
<!--略-->

然後我選擇在 app/ 下建立一個 resources 目錄,用來放置資源檔:

;Filename: categories.txt
;Language: en-US
View=View
Edit=Edit
Delete=Delete
AddNewCategory=Add a new Category
;Filename: categories.zh-tw.txt
;Language: zh-tw
View=檢視
Edit=編輯
Delete=刪除
AddNewCategory=加新類別

這裡要特別注意,把文字檔的編碼存為 unicode 或是 utf-8,否則會有亂碼出現。

最後修改 default.build,以便把資源檔編譯進去,這裡我也只列出關鍵的幾行:

<!--略-->
<target name="build" description="Compile all source files">
<mkdir dir="${dir.bin}" />
<copy flatten="true" todir="${dir.bin}">
<fileset>
<include name="${dir.lib.castle}/**" />
<include name="${dir.lib.npgsql}/**" />
<include name="${dir.lib.mysql}/**" />
<include name="${dir.lib.migrator}/**" />
<include name="${dir.lib.nunit}/nunit.framework.dll" />
</fileset>
</copy>
<resgen todir="${dir.src.app}/resources/">
<resources>
<include name="${dir.src.app}/resources/*.txt" />
</resources>
</resgen>
<csc target="library" output="${dir.bin}/${project::get-name()}.dll">
<sources>
<include name="${dir.config}/Boot.cs" />
<include name="${dir.src.app}/**/*.cs" />
<include name="${dir.src.test}/**/*.cs" />
<include name="${dir.migrations}/**/*.cs" />
</sources>
<resources basedir="." prefix="ToDo">
<include name="${dir.src.app}/resources/*.resources"/>
</resources>
<references basedir="${dir.bin}">
<include name="System.Web.dll" />
<!--略-->

最重要的就是 resgen 這個區塊與 csc 裡面的 resources 區塊,resgen 是把文字檔轉換為 .resources 資源檔,而 csc 裡面的 resources 則是表示要把產生出來的 .resources 編譯進去。

好了,該修改的都修改了,接下來就是重新建立,輸入 nant 就會自動重新編譯。
有點美中不足的是,下面顯示頁次的部份仍然是英文,這是因為這些字串被寫死在 ScaffoldHelper.cs 裡面,我想下次再來修改這部份。

後記:

  • csc resources 所指定的 prefix 與 [Resource(“textres”, “ToDo.categories”)] 的第二個參數息息相關,不妨修改來試試看。
  • 網站文件有提到 LocalizationFilter 的部份,但是用了卻不行,有待繼續研究。