亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 15903 | 回復(fù): 13
打印 上一主題 下一主題

[學(xué)習(xí)]第二個 Ruby 程序 - 簡易 Web 服務(wù)器 [更新完畢] [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2007-08-21 22:28 |只看該作者 |倒序瀏覽
最近寫作業(yè)要求用 C++,用慣了 PHP 和 Java 再用 C++ 真是痛苦。所以,輕松一下,換個口味,寫點 Ruby 就當(dāng)休息一下吧(基本上,寫 PHP 和 Ruby 都算是一種娛樂,非常得開心,C++ 和 Java 就……)。

前言

照例先說廢話。以前剛看到 Ruby 的時候,常?吹 RoR 被用來跟 PHP 比較,覺得這些人很無厘頭:RoR 是一個框架,而 PHP 是一種語言,怎么比法?直到不久之前,才發(fā)現(xiàn),原來是自己想錯了。因為 Ruby 是一門程序語言,但不(只)是一門腳本語言(Scripting Language)。而 PHP 基本上可以算做是腳本語言,雖然現(xiàn)在也有可以編譯為二進制的辦法以及 GUI 編程等等,但主要還是以作為腳本語言的角色為主。所以,用 RoR 和 PHP 比較還是算合理的。

這次希望寫個有點意思的程序,那就寫個簡單的 Web 服務(wù)器吧。要直到 Ruby (自帶?)的 WEBrick 服務(wù)器也是用 Ruby 寫成的。

開始

依照慣例,下面的內(nèi)容并不會全部解釋。我仍然假設(shè)你至少對 PHP、Python、Perl 或者 JavaScript 或者類似語言有一定基礎(chǔ)。關(guān)于 Ruby 比較特別和神奇的部分將會解釋。因為是寫 Web 服務(wù)器,你至少應(yīng)該對 Socket 有一定了解,當(dāng)然也不用太深。開發(fā)環(huán)境仍然是 RDE,一個很方便小巧的綠色 Ruby IDE,雖然還有些 bug 不過已經(jīng)很不錯了,當(dāng)然 EditPlus 也可以,請參見 PHP 版關(guān)于 EditPlus 配置的文章(by HonestQiao)。

原理

首先簡單介紹一下這個服務(wù)器的原理。我們的程序?qū)⒆鱿旅鎺撞剑?br />
1. 建立一個 TCP Server。
  - 這個包括:建立一個 TCP Socket,監(jiān)聽(listen) 80 端口(因為我們做服務(wù)器)。
2. 處理客戶端的請求(request)。
3. 根據(jù)處理結(jié)果發(fā)送數(shù)據(jù)到客戶端。

當(dāng)然,在探索的過程中,我們將為它加上其它的功能。

按照「俄羅斯人偶開發(fā)法」……首先實現(xiàn)最最基本的邏輯。這個服務(wù)器暫時使用循環(huán)處理請求的辦法(也不全是),下次可以挑戰(zhàn)用線程來分別處理各個請求。

雛形


  1. require 'socket'

  2. server = TCPServer.new('127.0.0.1', 80)

  3. while (session = server.accept)
  4.     session.gets
  5.     session.print "HTTP/1.1 200/OK\rContent-type: text/html\r\n\r\n"
  6.     session.print <<HTML
  7. <html>
  8.     <head></head>
  9.     <body>
  10.     Hello, World!
  11.     </body>
  12. </html>
  13. HTML
  14.     session.close
  15. end
復(fù)制代碼


這就是一個簡單得不能再簡單的 Web 服務(wù)器了。運行之后,在瀏覽器中訪問,即可看到 Hello, World! 字樣。

現(xiàn)在來看看這段代碼是什么意思。

首先,所有 socket 相關(guān)的類都在 'socket' 這個庫里面,所以,先 require 'socket'。

第二句是 Ruby 提供的一個快捷方式 TCPServer。這個類專門用于建立 TCP 服務(wù)器,新建 socket 和 listen 等等操作已經(jīng)封裝好了。注意這是最簡單的程序,并沒有加入任何檢錯代碼。TCPServer.new 有兩個參數(shù),一個是要綁定的 IP (或者域名),一個是端口(或者服務(wù))。這里我們綁定本機地址,端口選擇 Web 服務(wù)器最常用的 80。

下面做的就是不停接受(accept)新進的連接,并進行處理。由于 Ruby 提供和普通 I/O 一樣的 socket 方法,我們可以直接使用 gets 來獲取客戶端的請求(request)信息。雖然我們暫時不使用這個信息,但是這一步也是必須的。然后,簡單的 HTTP/1.1 頭信息。然后是輸出一個簡單的 HTML 文件。最后關(guān)閉這個會話。

注意 Ruby 的 HEREDOC 使用方法。很奇怪 Ruby 使用兩個 << 表示 HEREDOC,倒不是因為 PHP 用 3 個而奇怪,而是因為 << 在 Ruby 中是一個非常常用的操作符(連附加項目到數(shù)組都是用它)。當(dāng)然也許習(xí)慣也就好了吧。其它規(guī)則和一般 HEREDOC 一樣,只是不用分號結(jié)尾。

第一個俄羅斯人偶

現(xiàn)在,我們將為這個 Server 增加一個功能,那就是,讀出客戶端要求的文件,并返回數(shù)據(jù)。如果客戶端請求的是一個目錄,那么,簡單返回這個目錄的結(jié)構(gòu)信息。

首先,檢查這個功能需要什么數(shù)據(jù)(對象)。一目了然,需要的是一個文件類,需要一個顯示類,還有一個回應(yīng)類。文件類用于檢查、讀入文件,顯示類用于發(fā)送目錄數(shù)據(jù),回應(yīng)類用于封裝頭信息和數(shù)據(jù)以便于發(fā)送。

Ruby 的文件類 File 可以直接用于這個目的,但是,非?上У氖俏募惖奈臋n非常不整齊,而且在 ruby-doc.org 的排列也很讓人頭痛,在搜索和整理之后,找到了我們將用到的下面幾個方法:

File#open - 用于打開文件,附帶 block 可以自動關(guān)閉文件,這個在之前第一個 Ruby 程序里已經(jīng)用過了
File#directory? - 用于檢查文件是否是目錄
File#read(length) - 用于讀入文件至 length 字節(jié),并移動文件指針

顯示類主要用于用 HTML 來顯示目錄,將會用到 Dir 類的幾個方法:

Dir#open - 同 File
Dir#each - 用于遍歷目錄下的文件

現(xiàn)在開始寫代碼。首先寫最底層的回應(yīng)類:


  1. class Response
  2.     @@CRLF = "\r\n"
  3.     @@LFLF = "\n\n"

  4.     def initialize
  5.         @status
  6.         @body
  7.         @type
  8.     end

  9.     def status=(status_code)
  10.         case status_code
  11.             when 200
  12.                 msg = 'OK'
  13.             end
  14.         end
  15.         
  16.         @status = "HTTP/1.1 #{status_code}/#{msg}"
  17.     end
  18.    
  19.     # 這個方法是錯誤的,請到最后全代碼部分查看正確版本
  20.     def body=(body, type = 'text/html')
  21.         @body = body
  22.         @type = type
  23.     end
  24.    
  25.     def to_s
  26.         str = @status + @@CRLF
  27.         str += "Content-Length: #{@body.size}#{@@CRLF}"
  28.         str += "Content-Type: #{@type}#{@@CRLF}"
  29.         str += "Date: Wed, 22 Aug 2007 07:31:54 GMT#{@@CRLF}"
  30.         str += "Server: RubyServer 0.1#{@@LFLF}"
  31.         str += @body
  32.     end
  33. end
復(fù)制代碼


在這個類定義了兩個類變量(class variable),用兩個 @ 表示。CRLF 用于表示標準的分割 header 的符號,LFLF 是因為最后一個 header 信息之后,數(shù)據(jù)之前不能使用 CRLF,而必須使用兩個 linefeed。

initialize 里面定義的是兩個實例變量(instance variable),用一個 @ 表示,暫時不需要用到它們。

status= 方法用于設(shè)置 status 實例變量。這里先說說 Ruby 的方法名字的問題。AFAIK,Ruby 中的方法可以有三種結(jié)尾,問號,感嘆號和等號。問號代表問問題,即返回真假值;嘆號一般代表這個方法將會改變這個實例(而不是返回一個新的實例),或者這個方法可能有副作用云云。但問號和嘆號似乎是為了看代碼方便,好像并沒有強制作用。但是等號就有了:等號用于設(shè)置同名實例變量。也就是說,當(dāng)你使用 object.attr = sth 的時候,實際上不是真的在直接改變 attr 變量,而是訪問 attr=() 方法,sth 為參數(shù)。同理,當(dāng)你 puts obj.attr 的時候,也不是在直接訪問 attr 變量,而是在訪問 attr 方法。

當(dāng)然,這樣,就非常直觀地讓我們可以用 resp.status = 200 來設(shè)置 HTTP 狀態(tài)代碼,而在幕后,resp.status 實際上被補全成了完整的 HTTP 狀態(tài)頭信息。

Ruby 沒有 switch/case/default,而是改了個名字叫 case/when/else,就當(dāng)換了個口味吧。另外,印象中 Ruby 應(yīng)該是不支持 fall-though 的。

同理,body= 也是設(shè)置 body,默認為 text/html 類型。

to_s 是 Ruby 中把類轉(zhuǎn)換成字符串的標準函數(shù)。在這里,我們把所有信息并攏成為一個完整的 response,然后返回。當(dāng)然,這里偷懶沒有使用 return 語句,最后一個表達式的值自動返回。(我也墮落了,想當(dāng)初我是很痛恨這類 implicity 的)關(guān)于變量的字符串替換上次已經(jīng)說過了就不贅述;字符串的連接用 +。

另外,Ruby 似乎會自動定義 +=/-= 一類的快捷方式,如果你定義 +/- 的話(如果沒記錯)。

然后再來看顯示類,這個類讀入一個目錄字符串并遍歷和分析整個目錄的文件,然后 to_s 方法用于返回生成的 HTML 報告。


  1. class ViewDir
  2.     @@page = <<PAGE
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
  4. <html>
  5.     <head>
  6.         <title>Index of DIR
  7.         <style>
  8.         <!--
  9.             table, tr, td {
  10.                 border: 1px solid gray;
  11.                 border-collapse: collapse;
  12.                 table-layout: fixed;
  13.             }
  14.         -->
  15.         </style>
  16.     </head>
  17.     <body>
  18.         <table>
  19.             <tr>
  20.                 <td width="10%">Name</td>
  21.                 <td width="10%">Last Modified</td>
  22.                 <td width="5%">Size</td>
  23.             </tr>
  24.             ROW
  25.         </table>
  26.     </body>
  27. </html>
  28. PAGE
  29.     @@row = <<ROW

  30.             <tr>
  31.                 <td>NAME</td>
  32.                 <td>DATE</td>
  33.                 <td>SIZE</td>
  34.             </tr>
  35. ROW

  36.     def initialize(dirname)
  37.         @entries = ""
  38.         @content = @@page.gsub('DIR', dirname)

  39.         Dir.open(dirname) do |dir|
  40.             dir.each do |d|
  41.                 next unless (!File.directory?(d) and File.exists?(d))

  42.                 file = File.open(d) do |f|
  43.                     row = @@row.gsub('NAME', d)
  44.                     row.gsub!('DATE', f.mtime.to_s)
  45.                     row.gsub!('SIZE', f.stat.size.to_s)
  46.                     @entries += row
  47.                 end
  48.             end
  49.         end

  50.         @content.gsub!('ROW', @entries)
  51.     end

  52.     def to_s
  53.         @content
  54.     end
  55. end
復(fù)制代碼


首先我們可以試著測試一下這個類。注意在 WinXP 下面,訪問「..」,也就是上級目錄會出現(xiàn)異!窹ermission Denied」 (糾正一個錯誤,實際上是 File.open 目錄才會出錯),所以這里把 .. 也除外,到上級目錄的鏈接我們可以在 refinement 的時候做。這次的目標是簡易的 Web 服務(wù)器,那就讓它先實現(xiàn)最簡易的功能好了。


  1. x = ViewDir.new('.')
  2. puts x.to_s
復(fù)制代碼


上面的代碼可以測試這個類的成果,應(yīng)該還不錯吧。

現(xiàn)在解釋一下這個類中用到的東西。首先是類變量和成員變量,自不用說了。HEREDOC 也不用說了。需要注意的是,PHPer 熟悉的 str_replace 在 Ruby 中是 String 類的一個實例方法 gsub (還有自變版本 gsub!)。這里兩個版本都使用了,代碼不是非常的清晰和美觀,當(dāng)然,是有更好的辦法的,但是我還不太熟悉,這樣也能用,就先用著好了。

File#mtime 返回的是文件修改時間,是一個 Time 類,必須用 to_s 轉(zhuǎn)換為 String,當(dāng)然這里偷懶,沒有用自定義格式的時間,to_s 就 OK 了。另一個奇怪的東西是,size 是 File 的一個類方法但卻不是一個實例方法(不一致性!),要用 size,必須用 File::Stat 類,當(dāng)然這個類也不是不方便,因為也是內(nèi)置的東西,直接 file.stat 即可使用,只是有些不一致,不是很美觀和協(xié)調(diào)。這個類有 size 方法,可以直接使用。當(dāng)然,size 是 Fixnum 類(Ruby 的整數(shù)型),不能直接轉(zhuǎn)換為 String,還是必須 to_s?吹竭@里也許會覺得 Ruby 麻煩,覺得 PHP 真是太好了。其實是有那么一點點,但是,但是最重要的是這樣減少了很多無意中可能發(fā)生的錯誤,也是程序的邏輯更加的準確(雖然不一定更加清晰)。

然后需要注意的是,Ruby 中的 block 是會自動建立新的變量作用域(variable scope)的,也就是說 do...end 之間新建的內(nèi)容外部將不能訪問。

接下來讓我們把這些功能和類全部集中起來。

第二個俄羅斯人偶

在開始集中這些功能之前,我們需要做一些準備工作。Web 服務(wù)器是有其自己的根目錄的,比如 www 和 http_public 一類,我們這個服務(wù)器也要有一個根目錄。如果直接用 ViewDir 那么根目錄很有可能是系統(tǒng)的 root (自少在 WinXP 下面是),所以,我們必須設(shè)置一個服務(wù)器目錄。當(dāng)然要自己設(shè)置是很麻煩的,如果可以自動根據(jù)我們服務(wù)器的 rb 文件的位置設(shè)置就好了。當(dāng)然可以。

用過 PHP 的都知道 PHP 有幾個從 C 借來的魔法變量,所謂 magic variables,編譯器使用的 __FILE__ 和 __LINE__,Ruby 也有這兩個東西。不過 __FILE__ 只能得到當(dāng)前文件名,要用目錄?用 File.dirname(__FILE__)。

這里講一個 Ruby 的規(guī)則,因為 Ruby 的類方法和實例方法是不同的,不能混用,所以,在講解和寫文檔的時候,一般用 File#atime 來表示實例方法,用 File.atime 來表示類方法,這樣比較清晰。

最近作業(yè)比較繁多,就不詳細講解了,全代碼如下:


  1. require 'socket'

  2. class Response
  3.     @@CRLF = "\r\n"
  4.     @@LFLF = "\n\n"

  5.     def init
  6.         @status
  7.         @body
  8.         @type
  9.     end

  10.     def status=(status_code)
  11.         case status_code
  12.             when 200
  13.                 msg = 'OK'
  14.             when 400
  15.                 msg = 'Not Found'
  16.         end
  17.         
  18.         @status = "HTTP/1.1 #{status_code}/#{msg}"
  19.     end
  20.    
  21.     def body=(body)
  22.         if body.is_a?(Array)
  23.             @body = body[0]
  24.             @type = body[1]
  25.         else
  26.             @body = body
  27.             @type = 'text/html'
  28.         end
  29.     end
  30.    
  31.     def to_s
  32.         str = @status + @@CRLF
  33.         str += "Content-Length: #{@body.size}#{@@CRLF}"
  34.         str += "Content-Type: #{@type}#{@@CRLF}"
  35.         str += "Date: Wed, 22 Aug 2007 07:31:54 GMT#{@@CRLF}"
  36.         str += "Server: RubyServer 0.1#{@@LFLF}"
  37.         str += @body
  38.     end
  39. end

  40. class ViewDir
  41.     @@page = <<PAGE
  42. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
  43. <html>
  44.     <head>
  45.         <title>Index of DIR
  46.         <style>
  47.         <!--
  48.             * {
  49.                 font-family: courier new, arial, tahoma;
  50.                 font-size: 12px;
  51.             }
  52.             h1 {
  53.                 font-family: tims new roman;
  54.                 font-size: 25px;
  55.             }
  56.             table, tr, td {
  57.                 border: 0;
  58.                 table-layout: fixed;
  59.             }
  60.             td {
  61.                 cell-padding: 3px;
  62.             }
  63.         -->
  64.         </style>
  65.     </head>
  66.     <body>
  67.         <h1>Index of DIR</h1>
  68.         <table>
  69.             <tr>
  70.                 <td width="160px">Name</td>
  71.                 <td width="250px">Last Modified</td>
  72.                 <td width="30px">Size</td>
  73.             </tr>
  74.             <tr>
  75.                 <td colspan="3"><hr></td>
  76.             </tr>
  77.             ROW
  78.             <tr>
  79.                 <td colspan="3"><hr></td>
  80.             </tr>
  81.         </table>
  82.     </body>
  83. </html>
  84. PAGE
  85.     @@row = <<ROW

  86.             <tr>
  87.                 <td><a href="PATH">NAME</a></td>
  88.                 <td>DATE</td>
  89.                 <td>SIZE</td>
  90.             </tr>
  91. ROW

  92.     def initialize(dirname)
  93.         @entries = ""
  94.         @content = @@page.gsub('DIR', dirname[$root.size..dirname.size])

  95.         Dir.open(dirname) do |dir|
  96.             dir.each do |d|
  97.                 next unless (!File.directory?(d) and File.exists?(d))

  98.                 File.open(d) do |f|
  99.                     if d.size > 15
  100.                         name = d[0..5] + '...' + d[-5,5]
  101.                     else
  102.                         name = d
  103.                     end

  104.                     row = @@row.gsub('NAME', name)
  105.                     row.gsub!('PATH', d)
  106.                     row.gsub!('DATE', f.mtime.to_s)
  107.                     row.gsub!('SIZE', f.stat.size.to_s)
  108.                     @entries += row
  109.                 end
  110.             end
  111.         end

  112.         @content.gsub!('ROW', @entries)
  113.     end

  114.     def to_s
  115.         @content
  116.     end
  117. end

  118. server = TCPServer.new('127.0.0.1', 80)
  119. $root = File.dirname(__FILE__)

  120. while (session = server.accept)
  121.     request = session.gets.split(/\s/)
  122.    
  123.     if (request[0] != 'GET')
  124.         next
  125.     end

  126.     file = request[1]
  127.     file = $root + file

  128.     resp = Response.new

  129.     if not File.exists?(file)
  130.         resp.status = 400
  131.         resp.body = ""
  132.     elsif File.directory?(file)
  133.         resp.status = 200
  134.         resp.body = ViewDir.new(file).to_s
  135.     else
  136.         resp.status = 200
  137.         resp.body = File.new(file, 'rb').read, 'octet/application'
  138.     end

  139.     session.write resp.to_s
  140.     session.close
  141. end
復(fù)制代碼


這里修正一個錯誤:Ruby 是支持 attr=() 這樣的方法的,前面說過,但是很遺憾,這個方法并不想完整的方法一樣,支持多個參數(shù),而只支持一個參數(shù),所以,前面的 body=() 方法做了調(diào)整,這也算 Ruby 的一個 gotcha 吧。

另外,太長的字符串用 Ruby 的方式來截短了。注意這一行:


  1. name = d[0..5] + '...' + d[-5,5]
復(fù)制代碼


兩種數(shù)組下標 [] 的用法都涉及到了,也涉及到了負下標的用法。

Ruby 支持范圍,也就是說 0..5 就是 0 到 5 (包含),而三個點則是不包含(這個有些違背常理)。范圍有專門的 Range 類,有 each 方法可以直接遍歷。用于數(shù)組的下標的時候,將選取和返回一個包括這個數(shù)組從 0-5 的所有元素的新數(shù)組。當(dāng)下標是一個數(shù)組的時候,前一個代表從哪個開始,后一個代表共選取多少個。負下標代表從末尾開始數(shù)。

上面的語句意思是,「選擇 d 字符串的第 0、1、2、3、4、5 字節(jié),加上 ...,在加上 d 字符串的最后 5 個字節(jié)」。

其實還有另外一種辦法。那就是


  1. name = d.dup # d.clone
  2. name[5...-5] = '...'
復(fù)制代碼


這兩句的意思分別是,「復(fù)制一個 d 對象,并命名為 name」,「選擇 name 對象的第 5 至倒數(shù)第 5 字節(jié),并把一段替換成 ...」。從這里也看出了 Ruby 數(shù)組(及字符串)的靈活。當(dāng)然也有些容易混淆。


  1. @content = @@page.gsub('DIR', dirname[$root.size..dirname.size])
復(fù)制代碼


這一句是否有些奇怪?主要是第二個參數(shù)的部分吧。$root 是全局變量,代表著服務(wù)器根目錄的物理地址,或者說 full path。而后面的 dirname 是我們當(dāng)前目錄的地址。其實上面的那一段的意思就是,把服務(wù)器根目錄的地址從當(dāng)前目錄的地址中減掉。例如:


  1. $root = '/path/to/our/server'
  2. $requested_url = '/'
  3. $current_working_dir = '/path/to/our/server/'
復(fù)制代碼


因為必須要轉(zhuǎn)換成物理地址才能夠讀取文件,但是又不想把這個地址曝露給客戶端,所以用了上面的辦法。

這段代碼還用了一個 statement modifier 和一個比較新鮮的東西 unless。其實 unless 就是 if not。但是 unless 用在 statement modifier 的時候很好理解。


  1. next unless (!File.directory?(d) and File.exists?(d))
復(fù)制代碼


上面的代碼的意思是:「跳過這個!除非 d 存在而且不是目錄」。如果用 if not 的話:「如果文件不存在或者文件是目錄的話,跳過這個!」

傳說中 unless 在雙重否定的時候會比較清晰,但是個人覺得偶爾會搞混,看自己吧。

另外,Win 平臺下面讀二進制文件一定要用加 b 參數(shù),否則不能讀完。也因為這個,Win 平臺下面不能不打開二進制文件就直接讀,必須先打開(加 b 參數(shù)),然后再讀。(注意 File.read 和 File#read 都是存在的)

其它就沒什么說的了,還是老話,做作業(yè)的空閑寫著玩,不嚴謹、沒結(jié)構(gòu)、代碼質(zhì)量低、錯誤漏洞百出……等等都是正常的,不是我的作風(fēng),也不是 Ruby 的作風(fēng)……

另:這個服務(wù)器確實很簡易……不支持下級目錄、報錯都不會……等等,只是寫著完,若是要寫得比較能用,那就不在本文討論之列了,只希望能給大家一些 Ruby 的印象。希望能滿足那些不能被「簡單弱智的 example 代碼,枯燥的手冊,干癟的講解和理科生的翻譯」?jié)M足的人們。

希望大家看了能對 Ruby 產(chǎn)生興趣,也歡迎各位提出理性的討論、意見和建議。



Ruby 學(xué)習(xí)第二季精彩預(yù)告

Ruby 很強大,也很簡單,那么她的 GUI 功力如何呢?在給程序員們帶來歡樂的同時,Ruby 能否為廣大的用戶提供好的用戶界面呢?第三個 Ruby 程序?qū)⑹褂?Ruby 的贈品 GUI 庫 Tk,看看 Ruby 能否把更復(fù)雜的事情變得更簡單。

Ruby 已經(jīng)發(fā)明多年,卻因為英文文檔少而少有被人注意。在 Java 正處頹勢的時候,很多語言都慢慢地在嶄露頭角,它們都各司其職,朝著自己設(shè)計的方向發(fā)展,Ruby 也不例外。而今年來 RoR 的超高的開發(fā)效率一夜間讓人們認識了 Ruby,也在一夜間,幾乎所有的 Web 相關(guān)語言都有了自己類似于 RoR 的框架。第四個 Ruby 程序?qū)⑹褂?RoR,并順帶介紹 MVC,ActiveRecord 等等相關(guān)的技術(shù)(當(dāng)然是用人文的方式~)。

以上,希望各位喜歡~

[ 本帖最后由 dz902 于 2007-8-25 19:49 編輯 ]

論壇徽章:
0
2 [報告]
發(fā)表于 2007-08-21 23:39 |只看該作者
占位

論壇徽章:
0
3 [報告]
發(fā)表于 2007-08-22 10:41 |只看該作者
加油

論壇徽章:
0
4 [報告]
發(fā)表于 2007-08-22 11:16 |只看該作者
參觀

論壇徽章:
0
5 [報告]
發(fā)表于 2007-08-22 15:24 |只看該作者
原帖由 dz902 于 2007-8-21 22:28 發(fā)表
最近寫作業(yè)要求用 C++,用慣了 PHP 和 Java 再用 C++ 真是痛苦。所以,輕松一下,換個口味,寫點 Ruby 就當(dāng)休息一下吧(基本上,寫 PHP 和 Ruby 都算是一種娛樂,非常得開心,C++ 和 Java 就……)。

前言

...

LZ寫的相當(dāng)好,支持一下!

論壇徽章:
0
6 [報告]
發(fā)表于 2007-08-22 16:49 |只看該作者
謝謝各位的支持~

論壇徽章:
27
CU大;照
日期:2013-03-13 15:15:08CU大;照
日期:2013-05-20 10:46:38CU大;照
日期:2013-05-20 10:46:44CU大;照
日期:2013-09-18 15:24:09CU大牛徽章
日期:2013-09-18 15:24:20CU大;照
日期:2013-09-18 15:24:25CU大;照
日期:2013-09-18 15:24:31CU大;照
日期:2013-09-18 15:24:36CU大;照
日期:2013-09-18 15:24:41CU大;照
日期:2013-09-18 15:24:48CU大;照
日期:2013-09-18 15:24:52處女座
日期:2013-09-27 17:45:43
7 [報告]
發(fā)表于 2007-10-16 17:05 |只看該作者
剛剛學(xué)習(xí)了一下ruby的語法,好多符號阿

論壇徽章:
0
8 [報告]
發(fā)表于 2007-10-17 09:53 |只看該作者
支持一下dz902

論壇徽章:
0
9 [報告]
發(fā)表于 2007-10-17 21:08 |只看該作者
好,支持!
:wink:

論壇徽章:
0
10 [報告]
發(fā)表于 2007-10-18 22:19 |只看該作者
希望繼續(xù)
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP