Ruby程式語言入門導覽

  • 5,108 views
Uploaded on

http://whoswho.openfoundry.org/workshop/details/88--ruby.html …

http://whoswho.openfoundry.org/workshop/details/88--ruby.html
的簡報

More in: Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
5,108
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
98
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1.
      RUBY 程式語言 入門導覽
      [email_address]
    • 2010.05.23@ OSSF
  • 2.
      Who am I?
      • 鄧慕凡, Ryudo
        • http://blog.freebbs.tw
        • 3. twitter: ryudoawaru
      • 從 2007 年初開始使用 Ruby(Rails)
      • 4. TOMLAN Software Studio founder
        • http://www.freebbs.tw
        • 5. http://www.gameclub.tw
  • 6. 講義
    • http://ryudo.freebbs.tw/
  • 7.
      什麼是 Ruby?
      • 開放原碼、物件導向的直譯式   (interpreted) 腳本 (script) 程式語言
      • 8. 簡單哲學、高生產力
      • 9. 精巧、自然的語法
      • 10. 創造者 Yukihiro Matsumoto
        • 靈感來自 Lisp, Perl, 和 Smalltalk
        • 11. 減少編程時候的不必要的瑣碎時間,令編寫程序的人高興
  • 12.
      irb: Interactive Ruby    馬上動手練習
      開啟終端機: ryudo@ryudo-x61:~$ irb irb(main):001:0> 1+3 => 4 irb(main):002:0> 'hello' + ' world' => "hello world"
  • 13.
      IRB(Interactive Ruby Shell)
      • 互動式交談
        • 每次指令的結果都會在下一行輸出
      • 簡單測試的最佳工具
  • 14.
      Ruby 是直譯式強型別語言
      • 直譯式語言
        • Ruby/PHP/Perl/Python/VB
      • 編譯式語言
        • Java/C/C++
      • 強型別
        • Ruby/JAVA
      • 弱型別
        • PHP
  • 15.
      Ruby 是強型別 (Strongly typed) 語言
      irb(main): 003 : 0 > i= 1   => 1   irb(main): 004 : 0 > 'hello' + i 
      TypeError : can 't convert Fixnum into String from (irb):4:in `+' from (irb): 4
  • 16.
      整數 Integer
      10 5 10000 9999999999999999999999 0 -100000
  • 17.
      浮點數 Float
      1.1 -100.28 3.14159
  • 18. 輸出
    • PUTS
      • 輸出結果值的.to_s,然後換行
    • P
      • 輸出結果值的.inspect,然後換行
      • 19. 通常拿來debug
  • 20. 輸入
    • gets
      • 得到按下enter前的內容
      • 21. 內容是字串
      • 22. 後接.chomp避免把換行也加進來
  • 23.
      整數四則運算 ( 結果整數 )
    1 + 1 #= 2 200 * 3 #= 600 10 - 999 #= -989 100 / 20 #= 5 100 / 30 #= 3
  • 24.
      浮點數四則運算 ( 結果 Float)
      irb(main): 001 : 0 > 5 * 2.0 => 10.0 irb(main): 002 : 0 > 2.0 + 100.2 => 102.2 irb(main): 003 : 0 > 2.2 * 5.5 => 12.1 irb(main): 004 : 0 > 100.0 / 4.0 => 25.0 irb(main): 008 : 0 > 9.0 / 2.0 => 4.5
  • 25.
      更多運算
      puts 5 * ( 10 + 5 ) - 13
    • puts 999 + ( 31456 / ( 13 * 7 ) ) * -70
  • 26.
      字串 String
      puts 'Hello, world!'
    • puts '' puts 'Good-bye.'
    • 27. puts ' 馬上就會好 '
  • 28. Try it out!
  • 29. 字串的建構
    • 'abc'單引號
      • 裡面可包含"
    • "def"雙引號
      • 可內插變數
      • 30. 可內插控制字元( 等..)
  • 31.
      字串可 + 不可 -
      irb(main): 008 : 0 > 'abc' + 'def'
    • => "abcdef"
    • 32. irb(main): 010 : 0 > 'abc' .concat( 'def' )
    • 33. => "abcdef"
    • 34. irb(main): 009 : 0 > 'abc' - 'def'
    • 35. NoMethodError : undefined method `-' for "abc":String
  • 36.
      更多字串函式
      var1 = 'stop'
    • var2 = 'foobar'
    • 37. var3 = "aAbBcC"
    • 38. var4 = ' 那很好哇 '
    • 39. puts var1.reverse # 反轉
    • 40. puts var2.length # 長度
    • 41. puts var3.upcase # 轉大寫
    • 42. puts var3.downcase # 轉小寫
    • 43. puts var4.strip # 左右去空白
  • 44. 格式化字串
    • sprintf(輸出變數)
    • 45. printf(輸出畫面)
    • 46. 風格類似C的同名函式
    • 47. %s字串, %d整數, %f浮點數..
  • 48. 格式化字串 i1 = 123 f1 = 456.789 printf( ' 我有 %d 元 ' , i1) # 我有 123 元 printf( '%0.5d' , i1) #00123 printf( '%3.5f' , f1) #456.78900
  • 49. 練習1
    • 輸出詢問名稱和年紀的訊息,再於畫面中show出對話
  • 50. 練習1 puts 'Hello there, and what ' s your name?' name = gets.chomp puts 'Your name is ' + name + '? What a nice name!' puts 'Pleased to meet you, ' + name + '. :)'
  • 51. 執行
    • ruby xx.rb
  • 52.
      完全物件導向的語言    包括字串和數字都是物件,無內建型別
      irb(main): 001 : 0 > 'abc123' .upcase
    • => "ABC123"
    • 53. irb(main): 002 : 0 > 'abc123' .class
    • 54. => String
    • 55. irb(main): 003 : 0 > 'abc123' == String .new( 'abc123' )
    • 56. => true
    • 57. irb(main): 004 : 0 > 5 .times{puts ' 你累了嗎 ?' }
    • 58. 你累了嗎 ?
    • 59. 你累了嗎 ?
    • 60. 你累了嗎 ?
    • 61. 你累了嗎 ?
    • 62. 你累了嗎 ?
    • 63. => 5
  • 64.
      ( 區域 ) 變數 Variable 必需是小寫英文字開頭
    a = 100 b = 10.5 a * b #= 1050.0 c = 'SO' d = 'GO' c+d #= "SOGO"
  • 65. 全域變數
    • 以$開頭的變數
  • 66. 字串內插變數 i1 = 123 puts "Iam#{i1}" #"Iam123"
  • 67.
      型別轉換 Conversions
    var1 = '2' var2 = 4 var3 = 4.5 var1.to_i * var2 #= 8 var1.to_f * var3 #= 9.0 var3.to_s + var1 #= 注意是字串
  • 68.
      常數 Constant    大寫開頭
      irb(main): 001 : 0 > foo = 1
    • => 1
    • 69. irb(main): 002 : 0 > foo = 2
    • 70. => 2
    • 71. irb(main): 003 : 0 > Foo = 1
    • 72. => 1
    • 73. irb(main): 004 : 0 > Foo = 2
    • 74. (irb): 4 : warning: already initialized constant Foo
    • 75. => 2     # 雖然警告但其實 OK
    • 76. irb(main): 005 : 0 > RUBY_PLATFORM
    • 77. => "i686-linux"
    • 78. irb(main): 006 : 0 > ENV     # 會噴出一堆環境變數
  • 79. Nil 空值
    • 表示為空
    • 80. 不等於false/0/空字串('')
    irb(main): 001 : 0 > nil => nil irb(main): 002 : 0 > nil == false => false irb(main): 003 : 0 > nil == '' => false
  • 81. 註解 #
    • 以#開頭之後為註解
  • 82. 陣列 Array http://ruby-doc.org/core-1.8.7/classes/String.html [ 1 , 2 , 3 , 4 ] [ 1 , 'abc' , false ,[ nil , nil ]] # 多維陣列 [ 1 , 2 , 3 , 4 ].reverse # [4, 3, 2, 1] [ 1 , 'abc' , false ,[ nil , nil ]].size # 4 [ 1 , 'abc' , false ,[ nil , nil ]].flatten # [1, "abc", false, nil, nil]
  • 83. 索引操作
    • [n] 取得第n個
    • 84. [n..m] 取得第n至m個
    • 85. [n...m] 取得n至m-1個
    • 86. [n,len]取得n開始的len個
  • 87. 索引操作 arr = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] p arr[ 2 .. 3 ] #[3, 4] p arr[ 2 ... 4 ] #[3, 4] p arr[ 2 , 2 ] #[3, 4]
  • 88. 陣列相加 [ 1 , 2 , 3 ] + [ 4 , 5 , 6 ] # [1, 2, 3, 4, 5, 6] [ 1 , 2 , 3 ].concat [ 4 , 5 , 6 ] # [1, 2, 3, 4, 5, 6]
  • 89. 更多陣列函式(1) ossf=[ 'whoswho' , 'openfoundry' , 'org' ] ossf << 'tw' # [&quot;whoswho&quot;, &quot;openfoundry&quot;, &quot;org&quot;, &quot;tw&quot;] ossf.push 'www2' # [&quot;whoswho&quot;, &quot;openfoundry&quot;, &quot;org&quot;, &quot;tw&quot;, &quot;www2&quot;] ossf.unshift 'www2' # [&quot;www2&quot;, &quot;whoswho&quot;, &quot;openfoundry&quot;, &quot;org&quot;, &quot;tw&quot;, &quot;www2&quot;
  • 90. 更多陣列函式 ossf.pop # 返回從後面取出的值 , 但陣列本身已被改變 #= [&quot;www2&quot;, &quot;whoswho&quot;, &quot;openfoundry&quot;, &quot;org&quot;, &quot;tw&quot;] ossf.shift ## 返回從前面取出的值 , 但陣列本身已被改變 #= [&quot;whoswho&quot;, &quot;openfoundry&quot;, &quot;org&quot;, &quot;tw&quot;]
  • 91. 字串陣列共通的方法
    • 操作索引
      • [n]、[m..m]、[n,len]等
    • Enumerable類方法
      • each、map等
    • 連接、逆轉相關方法
      • reverse、concat、delete
  • 92. 取得字串的字元碼 'Abcde123HG' .bytes.to_a => [ 65 , 98 , 99 , 100 , 101 , 49 , 50 , 51 , 72 , 71 ] 'Abcde123HG' [ 1 ] => 98
  • 93. 雜湊 Hash h = { :abc => 123 , 'def' => 456 } #= {&quot;def&quot;=>456, :abc=>123} h[ :abc ] #= 123 h[ 'def' ] #= 456
  • 94. 字串符號 Symbols
    • 不會變動的唯一辨識符
    h2 = { :abc => 123 , 'abc' => 456 } #= {&quot;abc&quot;=>456, :abc=>123} :abc .object_id #= 263138 # 不論宣告幾次都是一樣的實體 'abc' .object_id #= 84140440 'abc' .object_id #= 84137350 # 字串重複宣告後就不一樣實體
  • 95. PUTS/P 範例 irb(main): 011 : 0 > h = { :abc => 123 } => { :abc => 123 } irb(main): 012 : 0 > p h { :abc => 123 } irb(main): 013 : 0 > puts h abc123 irb(main): 014 : 0 > puts :ossf ossf irb(main): 015 : 0 > p :ossf :ossf
  • 96. 流程控制
  • 104. 結構控制
  • 107. if puts &quot; 請輸入你的月薪 &quot; your_money = gets.to_i if your_money >= 100000 puts &quot; 哩金好野 &quot; elsif your_money >= 22000 puts &quot; 還好比 22K 多 &quot; else puts ' 唉 ' end
  • 108. unless
    • 除了沒有elsif外都跟if一樣,只是條件相反
  • 109. CASE aaa = [ 1 , 'abc' , 1.3 ] p aaa printf( ' 你要確認哪一個 ?' ) idx = gets.to_i case aaa[idx] when String puts &quot; 這是一個字串 &quot; when Integer puts &quot; 這是一個整數 &quot; when Float puts &quot; 這是一個浮點數 &quot; when Numeric puts ' 這是一個數字 ' else puts &quot; 這是其它類型的物件 &quot; end
  • 110. 三元運算子 EXPRESSION ? (True Condition):(False Condition) a = 10 ; b = 100 a > b ? ( &quot;#{a} > #{b}&quot; ):( &quot;#{a} < #{b}&quot; ) #=> &quot;10 < 100&quot;
  • 111. 迴圈 10 .times do puts ' 那很好啊 ' end for i in 1 .. 10 puts i end x = 100 while x > 10 x = x - 10 puts x end x = 100 until x <= 10 x = x – 10 next if x == 50 # 跳過下一步繼續 puts x end abc = [ 1 , 2 , 3 ] loop do abc.pop p abc break if abc.empty? # 跳出 end
  • 112. 真或假
    • 只有nil 和 false為假,其它為真
    • 113. 所以空字串和0也是真
  • 114. 練習2 : 猜數字
    • 亂數產生一個數字
      • rand(20)會產生0~20間的隨機數字
      • 115. 避免0
    • 輸入一個數字
    • 116. 猜對了就跳出
    • 117. 猜錯了就顯示猜錯了
      • 差10顯示差很大
      • 118. 10比內顯示接近了
  • 119. 練習2 : 猜數字 randnum = 0 loop do randnum = rand( 20 ) break if randnum > 0 end 5 .times do print ' 請輸入一個數字 :' num = gets.chomp.to_i if num == randnum puts ' 猜對了 ~YEAH!' break end if num - randnum >= 10 puts &quot; 猜的大很多 &quot; elsif (num - randnum) < 10 && (num - randnum) >= 1 puts ' 猜的大一點 ' elsif randnum - num >= 10 puts ' 猜的小很多 ' else puts ' 猜的小一點 ' end end
  • 120. 正規表示式 phone = &quot;002-2882-5252&quot; if phone =~ /( d +) - ( d +) - ( d +)/ area = $1 first = $2 second = $3 end p [area, first, second]
  • 121. Method 方法 依接收者分為三大類
    • 實體方法(Instance Method)
    • 122. 類別方法(Class Method)
    • 123. 函式性的方法
  • 124.
    • 實體方法 (Instance Method)
    • 屬於某個類別new出來的「物件實體」之方法
    • 125. 接收者(self)為物件實體
    'abcdef' .reverse #=> &quot;fedcba&quot;
  • 126.
    • 類別方法(Class Method)
    • 類別本身的方法
    • 127. 接收者(self)為類別
    • 128. 建立物件的.new即為類別方法
    irb(main): 009 : 0 > a = Date .today => #<Date: 4910677/2,0,2299161> irb(main): 010 : 0 > puts a 2010 - 05 - 22
  • 129.
    • 函式性的方法
    • 沒有接收者也能執行的方法
    • 130. 其實並非沒有接收者,只是被省略的情形
    sprintf( &quot;%d %04x&quot; , 123 , 123 ) #=> &quot;123 007b
  • 131. 定義函式
    • Def 函式名稱..end
    • 132. 以return返回值
    • 133. 如無設定return,以最後一個運算式的結果為return
    def hello (name) sprintf( ' 哈囉 %s' , name) end
  • 134. 定義函式之參數
    • def( 參數 ..)
    • 135. 可設定預設值,表示可省略
    • 136. 可省略者「必需」在不可省略者之前
    def showmanytimes (text2show, times = 10 ) #=> OK! times.times{puts text2show} end def showmanytimes (times = 10 , text2show) # => 錯誤 times.times{puts text2show} end
  • 137. ? 與 ! 的慣例
    • 函式定義以?結尾者
      • 表示回傳值為boolean
    • 函式定義以!結尾者
      • 表示會改變接收者本身
    irb(main): 001 : 0 > [ 1 , 2 , 3 , 4 ].empty? => false irb(main): 002 : 0 > [ 1 , 2 , 3 , 4 ,[ 5 , 6 ]].flatten => [ 1 , 2 , 3 , 4 , 5 , 6 ]
  • 138. 類別 (Class) 與實體 (Instance)
    • 類別 -> 模子
    • 139. 實體 -> 模子印出來的
    • 140. Ruby的萬物皆類別!
    ' 我愛 OSSF' .class => String
  • 141. 定義類別 class Duck def initialize (name) @name = name end def quack # 實體方法 &quot;#{ @name } is quacking!&quot; end end d = Duck .new( ' 唐老鴨 !' ) puts d.quack # 唐老鴨 ! is quacking! 建構式 ! 物件實體變數
  • 142. 定義類別 class Car @@amount = 0 def initialize (name) @name = name @@amount += 1 end def name= (val) @name = val end def name @name end def self . amount @@amount end end c1 = Car .new( ' 霹靂車 ' ); c2 = Car .new( ' 火戰車 ' ) c3 = Car .new( 'Focus' ); c3.name = 'Focus ST' puts &quot; 現在有 &quot; + Car .amount.to_s + &quot; 台車了 &quot; 物件類別變數 實體方法
  • 143. 類別定義內也可以執行程式 class Car @@amount = 0 def initialize (name) @name = name @@amount += 1 end attr_accessor :name def self . amount @@amount end end class Car @@amount = 0 def initialize (name) @name = name @@amount += 1 end def name= (val) @name = val end def name @name end def self . amount @@amount end end =
  • 144. 建立物件變數的存取函式
    • attr_accessor
      • 等於下面兩者相加
    • attr_writer
      • 只有寫入 代替def xxx=(val) end
    • attr_reader
      • 只有讀取 代替 def xxx end
  • 145. Public/Protected/Private
    • Public
      • 預設值,無限制呼叫對象
    • Protected
      • 繼承者可以呼叫,外部禁止,但同類別(含子類別)的其它實體可以呼叫
    • Private
      • 繼承者可以呼叫,外部禁止同類別(含子類別)的其它實體 不可以 呼叫
  • 146. 私有/保護 定義方式 class Abc def pub ... end def priv ... end def prot ... end private :priv public :pub protected :prot end class Abc public def pub ... end private def priv ... end protected def prot ... end end =
  • 147. 類別之繼承
    • 萬物皆繼承Object這個類別的子類
    • 148. 被繼承者為父類別(superclass)
    • 149. 繼承者為子類別(subclass)
  • 150. 繼承類別 class Vehicle attr_accessor :tires end class Tire attr_accessor :size end class Car < Vehicle def initialize (name) @tires = [] 4 .times{ @tires << Tire .new} end end class Motorcycle < Vehicle def initialize (name) @tires = [] 2 .times{ @tires << Tire .new} end end
  • 151. 探索繼承類別 c = Car .new( 'Mondeo 2.0' ) puts c.is_a?( Vehicle ) #true puts c.class.superclass #Vehicle
  • 152. 走訪迴圈 langs = [ 'VB' , 'C#' , 'C' , 'JavaScript' ] langs.each do |lang| puts &quot; 我會 #{lang}&quot; end 輸出: # 我會 VB # 我會 C# # 我會 C # 我會 JavaScript
  • 153. 迭代器 iterator
    • 不同於for或while,迭代器是一種走訪接收者(通常是陣列或陣列的子類)元素的「方法」
    • 154. do..end是迭代器方法的參數,可以將其代換為{},此類參數通稱為「code block」,也稱作匿名函式
  • 155. Code Block
    • Ruby主要特色之一
    • 156. 由於是一種匿名函式,故可接收參數
    • 157. 習慣Ruby的人不會常用for/while,會使用iterator和code block
  • 158. Code block 10 .times{|x| puts x} # 輸出 0 到 9 ( 1 .. 9 ).each{|x| puts x} #1 到 9 ( 1 ... 9 ).each{|x| puts x} #1 到 8 arr3 = [ 'ggg' , 123 , Time .now] arr3.each_with_index{|x, i| puts &quot; 第 #{i+1} 個元素的類別是 :#{x.class.to_s}&quot; } # 第 1 個元素的類別是 :String # 第 2 個元素的類別是 :Fixnum # 第 3 個元素的類別是 :Time
  • 159. 進階Code Block arr = [ 1 , 2 , 3 , 4 , 5 , 6 ] #=> [1, 2, 3, 4, 5, 6] arr.map{|a| a+ 10 } #=> 造出新陣列 [11, 12, 13, 14, 15, 16] arr.select{|a| a > 3 } #=> 只挑選大於 3 者 [4, 5, 6] arr.reject{|a| a> 3 } #=> 和 select 相反 [ 4 , 5 , 1 , 2 , 3 ].sort{|a, b| a <=> b} #=> 基本排序
  • 160. 進階Code Block arr1 = [ 'abc' , 'whoswho.openfoundry.org' , 'OSSF' ] arr1.sort_by{|w| w.length} # 用字數排序 #=> [&quot;abc&quot;, &quot;OSSF&quot;, &quot;whoswho.openfoundry.org&quot;] arr2 = [ 5 , 10 , 15 , 20 , 25 ] arr2.inject{|sum, x| sum += x } # 計算總合 => 75
  • 161. Code Block應用 # 一般檔案操作寫法 fc = open( 'abc.html' , 'w' ) fc.puts( '<html>' ) ..... fc.puts( '</html>' ) fc.close # 關閉檔案指標 # 使用 Code Block open( 'abc.html' , 'w' ) do |fc| fc.puts( '<html>' ) ..... fc.puts( '</html>' ) end # 無需呼叫 close
  • 162. 練習3
    • 建立一個有多個字串的陣列
    • 163. 將每個元素變大寫再反轉後結合在一起
    • 164. 使用code block/inject
  • 165. 練習3 def my_str_arr_processer (arr) return arr.inject( '' ){|s, a| s.concat(a.upcase.reverse)} end p my_str_arr_processer([ 'ab' , 'c' , 'g88' ])
  • 166. 練習4擴充字串
    • 擴充String類別
    • 167. 加入find_capital_letters方法
      • 尋找出大寫字母回傳
      • 168. 大寫字母的範圍:65~90
      • 169. 使用each_char方法尋遍全字串,或是bytes.to_a
  • 170. 練習4 class String def find_capital_letters s2r = '' self .each_char{|c| cc = c[ 0 ].to_i s2r.concat(c) if cc >= 65 && cc <= 90 } return s2r end end puts 'SUSE Linux' .find_capital_letters
  • 171. Yield and Method 在函式中使用 yield 來執行 code block def test_block puts &quot;I love Ruby ,&quot; yield end test_block{ puts 'Ruby loves programmers!' } # 顯示 I love Ruby , Ruby loves programmers!
  • 172. Yield and Method 在函式中使用 yield 來執行 code block def to_div (times) buffer = '<DIV>' times.times{|x| yield (buffer, x)} buffer.concat '</DIV>' end divhtml = to_div( 3 ) do |buf, x| buf.concat &quot;<p>No.#{x+1}</p>&quot; end puts divhtml # <DIV><p>No.1</p><p>No.2</p><p>No.3</p></DIV>
  • 173. Proc object 將 code block 明確轉成物件 def test_block (&block) # 注意 & printf &quot;I love Ruby ,&quot; block.call end def to_div (times, &block) # 注意 & buffer = '<DIV>' times.times{|x| block.call(buffer, x)} buffer.concat '</DIV>' end blk1 = Proc .new{ puts( 'Ruby loves programmers!' )} blk2 = lambda{|buf, x| buf.concat &quot;<p>No.#{x+1}</p>&quot; } test_block(&blk1) puts to_div( 3 ,&blk2) 傳參數以及方法宣告皆需要加 & 來明確告知
  • 174. 傳遞不定參數
    • Def xxx(*args)
    • 175. 在方法內被視為陣列
    def abc(*args) buf = '' args.each{|x| buf.concat yield (x)} return buf end abc( 'I' , 'LOVE' , 'OSSF' ) do |inner_text| &quot;<p>#{inner_text}</p><BR/>&quot; end # 輸出 #<p>I</p><BR/><p>LOVE</p><BR/><p>OSSF</p>
  • 176. 參數尾 Hash 可省略 { } def tag_with_html (tag_name, inner_text, html_options) buf = &quot;<#{tag_name}&quot; html_options.each do |opt, val| buf.concat(sprintf( ' %s=&quot;%s&quot; ' , opt.to_s, val.to_s)) end buf.concat &quot;>#{inner_text}</#{tag_name}>&quot; return buf end puts tag_with_html( 'td' , 'Ruby Programming' , :bglocor => 'Red' , :width => 100 ) #<td width=&quot;100&quot; bglocor=&quot;Red&quot; >Ruby Programming</td> puts tag_with_html( 'td' , 'Ruby Programming' , { :bglocor => 'Red' , :width => 100 }) # 結果相同
  • 177. 例外 Exception begin ..... rescue StandardError => ex #ex 為例外物件 p ex # 秀出 error 的詳細 ensure ..... # 無論如何都要執行的內容 end
  • 178. 例外 Exception
    • rescue後若有接例外類別名稱,代表只處理該例外類別的例外,不指定則處理一切例外
    • 179. 「$!」為最後發生例外物件,「$@」為發生錯誤的行號等資訊
  • 180. Module
    • 只有方法部份的集合體
    • 181. 無實體
    • 182. 用途:
      • 類似單例(Singleton)類別
      • 183. 命名空間(Name Space)
      • 184. Mix in
  • 185. Module for Singleton Class module HtmlHelper HTML_ESCAPE = { '&' => '&amp;' , '>' => '&gt;' , '<' => '&lt;' , '&quot;' => '&quot;' } def self . h (s) s.to_s.gsub( /[&&quot;><]/ ){ |special| HTML_ESCAPE [special] } end end puts HtmlHelper .h( '<img src=&quot;abc.gif&quot;/> 我是圖片 ' ) #&lt;img src=&quot;abc.gif&quot;/&gt; 我是圖片
  • 186. Module for Namespace module Forum class Member # 類別全名為 Forum::Member .... end class Topic #Forum::Topic end end
  • 187. Module for Mix-in 多重繼承之實現 module ShareMod def subject ... end end class Forum include ShareMod end class SubForum include ShareMod end #Foum 和 SubForum 都會有 subject 的 instance method 間接實現了 多重繼承
  • 188. 動態型別 (duck typing) 不管黑貓白貓,會抓老鼠的都是好貓 class PersianCat def find_mice # 抓老鼠 end end class RussianBlueCat def find_mice # 抓老鼠 end end
  • 189. 動態型別 (duck typing) 不論出身正確 ( 參數型別 ) ,只論達成目標 ( 方法 ) def fetch_and_reverse (arr, idx) return arr[idx].reverse if arr[idx] && arr[idx].respond_to?( :reverse ) end aa = [ 'abc' , 'RyudoAwaru' , 'Linux' ] ha = { 0 => 'abc' , 1 => 'Ubuntu' } hb = { :first => 'RedHat' , :second => 'Suse' } p fetch_and_reverse(aa, 1 ) #&quot;urawAoduyR&quot; p fetch_and_reverse(ha, 0 ) #&quot;urawAoduyR&quot; p fetch_and_reverse(hb, :second ) #&quot;esuS&quot; 只要 arr 能響應 [] 和 :reverse 這兩個方法即能達成目標
  • 190. Metaprogramming 用程式寫程式
  • 191. define_method class Movie def initialize (id, name) @id = id @name = name end QualityNames = [ :fullhd , :hd , :sd ] # 定義 fullhd_movie_file, hd_movie_file, sd_movie_file # 三個方法 QualityNames .each do |qt| define_method &quot;#{qt.to_s}_movie_file&quot; .to_sym do return &quot;/movies/#{qt.to_s}/#{ @id }.mp4&quot; end end end a = Movie .new( 123 , ' 阿凡達 ' ) puts a.hd_movie_file #/movies/hd/123.mp4
  • 192. Domain-Specific Language 領域特定語言 Class MyApp < Sinatra :: Base get '/books/*.*' do # matches /books/ruby-guide.html end get '/rooms/:id/index.html' do # matches '/rooms/123/index.html end end HTTP 動詞對應網址樣式, 即可做 WEB 伺服器的處理
  • 193. Method Missing class Wheel attr_accessor :radius def initialize (radius) @radius = radius end end class Car attr_accessor :wheels def initialize @wheels = [] 4 .times{ @wheels << Wheel .new( 30 )} end def method_missing (mname, *args) if mname.to_s =~ /wheel ( d )/ return @wheels [ $1 .to_i] end end end my_car = Car .new p my_car.wheel_1 #<Wheel:0x8f6dea4 @radius=30> Car 並不預設 wheel_1 執行 method_missing
  • 194. 物件方法查詢 object.methods # 列舉該物件的所有方法列表 object.private_methods # 列舉該物件的所有方法列表 object.protected_methods # 列舉該物件的所有方法列表 object.public_methods # 列舉該物件的所有方法列表 object.respond_to?( :method_name ) # 列舉是否支援某方法
  • 195. 練習5
    • 建立TextFileSearcher類別
      • 建構式:傳入檔名
      • 196. 方法:search_word
        • 輸入一個單字
        • 197. 一次讀取一行內容(gets)
        • 198. 如果該單字出現就show出這行,並顯示單字出現次數
        • 199. 檔案可去http://www.ruby-lang.org/en/about/
        • 200. 可用String#scan方法
  • 201. String#scan
    • 將找到的字串集合化為陣列
    • 202. 可接受字串或正規表示式
    $KCODE = 'u' stra = <<&quot;ABC&quot; 為紓解緊鄰中科的大肚山花園公墓,每逢清明節必塞車的窘境,台中市政府今年向男塾求援,希望他們能提供停車場成為公車轉運站。 「這怎麼可以,我們自己的客人也要停車呀」、「一天可湧入幾千位顧客耶,又是假日,客人一定會抱怨的啦」……員工七嘴八舌地回絕市政府的要求。不過董事長江田島平八卻二話不說,一口答應,員工一片譁然。 「捨三天生意,卻可以換來未來二十年的生意,這麼好的事情一定要做!」對無法理解的員工,江田島平八說,一旦停車場開放為接駁站,必定帶來龐大廣告效益,他的遠見說服了員工。 ABC p stra.scan ' 江田島平八 '
  • 203. 練習5 class TextFileSearcher def initialize (fn) @file_path = fn end def search_word (word) open( @file_path , 'r' ) do |fc| while line = fc.gets line.downcase! ar = line.scan(word.to_s) unless ar.empty? puts &quot;#{line} meets #{word} #{ar.size} times.&quot; end end end end end tt = TextFileSearcher .new( 'r.txt' ) tt.search_word( 'ruby' )
  • 204. RubyGems
    • 類似php的pear
    • 205. 指令 gem
      • List 列出現有的gem
      • 206. Install gemname 安裝
      • 207. Update gemname 升級
      • 208. Uninstall gemname 移除
  • 209. Sinatra Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort: http://www.sinatrarb.com
  • 210. 安裝
    • Sudo gem1.8 install sinatra
  • 211. Sinatra基本特性
    • A WEB Framework base on Rack.
    • 212. DSL化的URL
    • 213. 簡單、快速
  • 214. 第一隻 web app 執行 ruby myapp.rb, 然後打開瀏覽器 http://localhost:4567 # myapp.rb require 'rubygems' require 'sinatra' get '/' do 'Hello world!' end
  • 215. URL參數傳遞 get '/rooms/:id/index.html' do # matches '/rooms/123/index.html?width=500&height=300' params[ :id ] # => 123 params[ :width ] # => 500 params[ :height ] # => 300 end
  • 216. URL參數傳遞 *.* 變成 splash get '/books/*.*' do # matches /books/ruby-guide.html params[ &quot;splat&quot; ] # => [&quot;ruby-guide&quot;, &quot;html&quot;] end
  • 217. ERB Template
    • Code Block的最返回erb 樣板名稱
    • 218. 樣板名稱必需是symbol
    • 219. 樣板檔名是erb結尾
    • 220. 在views目錄下
    Class MyApp < Sinatra :: Base get '/' do @page_title = &quot; 輸入程式碼 !!&quot; erb :index # 用 index.erb 輸出 , layout.erb 做 layout end end
  • 221. 使用 template 建立 views 目錄 , 加入 index.erb 檔案 # myapp.rb require 'rubygems' require 'sinatra' get '/' do erb :index end
  • 222. 練習:index.erb <!DOCTYPE html> <html> <head> <title> Sinatra app </title> </head> <body> <% 10 .times do %> <p> <%= &quot;Hello #{params[ :name ]}!&quot; %> </p> <% end %> </body> </html>
  • 223. ERB語法
    • <%%>間為執行程式
    • 224. <%=%>間除執行程式外,會把結果直接layout在頁面上
    • 225. <%=erb :abc, :layout => false, :locals => {:post => @post}%> 可以在裡面render其它的erb
  • 226. LAYOUT file
    • 樣板間共用的部份
    • 227. HTML的上下文
    • 228. 預設layout.erb
    • 229. erb命令時可用:layout => :layout 做設定
  • 230. LAYOUT file <!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;> <html dir = &quot;ltr&quot; xmlns = &quot;http://www.w3.org/1999/xhtml&quot; > <head> <title> <%= @page_title %> </title> <meta http-equiv = &quot;Content-Type&quot; content = &quot;text/html; charset=utf-8&quot; /> </head> <body> <%= yield %> #yield 代表 erb 要 render 的部份 </body> </html>
  • 231. 傳遞變數到 Template get '/array' do @arr = [ &quot;aaa&quot; , &quot;bbb&quot; , &quot;ccc&quot; , &quot;ddd&quot; ] erb :array end <% @arr .each do |item| %> <p> <%= item %> </p> <% end %>
  • 232. POST FORM get '/' do erb :index end post '/query' do params[ :keyword ] end <form action = &quot;/query&quot; method = &quot;post&quot; > <p><input type = &quot;text&quot; name = &quot;keyword&quot; value = &quot;&quot; ></p> <p><input type = &quot;submit&quot; value = &quot;Submit&quot; ></p> </form>
  • 233. 練習6 將強調字詞粗體化
    • 去http://zonble.net/etc/bw.php製造廢文
    • 234. 生出表單,欄位是廢文內容以及要強調的字眼,例如「我的名字」部份
    • 235. 處理後將文章要強調的部份用<b>框起來
  • 236. String#gsub
    • 將符合第一個參數的字取代為第二個參數的字
    • 237. 可配合正規表示式接收BLOCK做樣式匹配更改內容
    'abc123def123GGG' .gsub( '123' , '456' ) => &quot;abc456def456GGG&quot;
  • 238. 練習6 #t6.rb require 'rubygems' require 'sinatra' get '/' do erb :index end post '/' do @text = params[ :text2parse ].gsub(params[ :word ], &quot;<b>#{params[ :word ]}</b>&quot; ) erb :post end
  • 239. 練習6 #index.erb <form action = &quot;/&quot; method = &quot;post&quot; > <input type = &quot;text&quot; name = &quot;word&quot; value = &quot;&quot; /><br/> <textarea name = &quot;text2parse&quot; cols = &quot;100&quot; rows = &quot;20&quot; ></textarea><br/> <input type = &quot;submit&quot; value = &quot; 送出 &quot; /> </form> #post.erb <p> <%= @text %> </p>
  • 240. ActiveRecord入門
  • 241. 什麼是 ORM ?
    • ORM: Object-Relational Mapping
    • 242. 將資料庫表格 (table) 對應到類別 (classe)
      • 提供類別方法對表格操作
    • 將資料庫列 (row) 對應到 物件 (object)
      • 提供物件方法對個別的資料做操作
    • 將資料庫欄位 (column) 對應到物件屬性 (object attribute)
  • 243. 開始操作 - 建立留言板 DB 借用 rails
    • rails MyPost
    • 244. cd MyPost
    • 245. script/generate model Post
  • 246. 建立DB 編輯 db/migrate 下的第一個 .rb class CreatePosts < ActiveRecord :: Migration def self . up create_table :posts do |t| t.string :author t.string :subject t.text :message t.timestamps end end def self . down drop_table :posts end end
  • 247. 建立DB
    • rake db:migrate
    • 248. Post DB建立完成
  • 249. Console
    • script/console
    • 250. 進階版的IRB
    • 251. 會把rails的環境load進來
  • 252. CRUD 操作 post = Post.new
    • Class method
      • Post.find #找id
      • 253. Post.create #新建並SAVE
      • 254. Post.new #建立不立刻SAVE
    • Instance method
      • post.save
      • 255. post.update_attributes #更新屬性並馬上存檔
      • 256. post.destroy
  • 257. CRUD 操作 post = Post.new p = Post .new( :author => 'OSSF' , :subject => ' 今天有 RUBY 課程 ' , :message => ' 那很好哇 ~~~~' ) p.save p.id # 輸出 1 puts Post .count # 輸出 1 p1 = Post .find( 1 ) p1 = Post .find_by_author( 'OSSF' ) p1.subject # 輸出 今天有 RUBY 課程 p1.update_attributes( :author => ' 自己填 ' , :message => ' 好累喔 !!~~' ) p p1 p1.destroy puts Post .count
  • 258. 練習:建立一些文章
  • 259. DSL化的搜尋
    • find_by_attrname -> 依照屬性名找出第一筆對應
    • 260. find_all_by_attrname -> 依照屬性名找出全部對應
  • 261. Model Validation 不正確的資料無法儲存
    • validates_presence_of
      • 必需存在
    • validates_length_of, :in, :minimum..
      • (字串)長度該多大
    • validates_numericality_of
      • 必需是數字
    • validates_uniqueness_of
      • 必需是唯一
    • validates_format_of
      • 符合正規表示式
  • 262. 練習:加上validates
    • 限制所有屬性不得為空
    • 263. 限制author的length必需大於3
    • 264. 限制subject的長度必需介於5~30間
  • 265. rake-Ruby的make
    • 方便設定執行指令的相依性
    • 266. 也DSL化
    namespace :gameclub do desc &quot; 自動移除論壇的操作 &quot; task :daily_remove => :environment do Billboard .should_remove.each do |bbs| if bbs.destroy puts &quot; 成功刪除論壇 ID#{bbs.id}, #{bbs.full_url}&quot; else puts &quot; 刪除論壇 ID#{bbs.id}, #{bbs.full_url} 失敗 !&quot; end end end end rake gameclub:daily_remove
  • 267. DB Migration?
    • 使用 Ruby 語法定義資料庫Schema
    • 268. 讓資料庫的修改也可以版本控制
    • 269. 跨資料庫通用(自訂指令除外)
  • 270. Sinatra實作網頁留言板
    • 建立views目錄
    • 271. 建立app.rb檔
    • 272. 將之前練習的views/layout.erb複製到這裡的views下
  • 273. 表象化狀態轉變 Representational State Transfer
    • Roy Fielding 博士在2000年他的博士論文中提出來的一種軟體架構風格。
    • 274. 相較於 SOAP、XML-RPC 更為簡潔容易使用
    • 275. 諸Web Service 中最為普遍的 API 格式, Amazon、Yahoo!、Google API 等均有提供。
  • 276. 7 Actions URL VERB 用途 /posts get 列表 /posts post 建立新留言 /posts/:id get show完整留言 /posts/:id/edit get 進入編輯頁 /posts/:id put 提交修改 /posts/:id/delete get 刪除 /posts/new get 新增頁面
  • 277. REST-STYLE URL PATTERN URL 行為 實體/類別 VERB /posts 無 類別 get /posts 無 類別 post /posts/:id 無 實體 get /posts/:id/edit edit 實體 get /posts/:id 無 實體 put /posts/:id/delete delete 實體 get /posts/new new 類別 get
  • 278. 前置作業
    • 建立DB(ORM)的連線
    • 279. require必要的lib
    require 'rubygems' require 'sinatra' require 'active_record' $DBCONFIG = YAML ::load File .open( &quot;config/database.yml&quot; , 'r' ).read ActiveRecord :: Base .establish_connection $DBCONFIG [ &quot;development&quot; ] Dir .glob( 'app/models/*.rb' ).each{ |f| require f} get '/' do redirect '/posts' end
  • 280. CONTROLLER get '/posts/new' do #new @post = Post .new erb :new end get '/posts' do #list @posts = Post .all erb :index end
  • 281. CONTROLLER put '/posts/:id' do #update puts &quot; 到了 put #{params.inspect}&quot; @post = Post .find(params[ :id ].to_i) if @post .update_attributes( :author => params[ :author ], :subject => params[ :subject ], :message => params[ :message ]) p @post redirect &quot;/posts&quot; else erb :edit end end
  • 282. CONTROLLER get '/posts/:id' do #show @post = Post .find(params[ :id ].to_i) erb :show end get '/posts/:id/delete' do #delete @post = Post .find(params[ :id ].to_i) @post .destroy redirect &quot;/posts&quot; end post '/posts' do #create puts &quot; 建文章 &quot; @post = Post .new( :author => params[ :author ], :subject => params[ :subject ], :message => params[ :message ]) if @post .save redirect &quot;/posts&quot; else erb :new end
  • 283. Views #new.erb <%=erb '_post_err' .to_sym, :locals => { :post => @post }%> <form action = &quot;/posts&quot; method = &quot;post&quot; > <%=erb '_form' .to_sym%> </form> #edit.erb <%=erb '_post_err' .to_sym, :locals => { :post => @post }%> <form action = &quot;/posts/<%= @post .id%>&quot; method = &quot;post&quot; > <input name = &quot;_method&quot; type = &quot;hidden&quot; value = &quot;put&quot; /> <p><a href = &quot;/posts/<%= @post .id%>/edit&quot; > 修改 </a></p> <%=erb '_form' .to_sym%> </form>
  • 284. VIEWS #_form.erb <table width = &quot;80%&quot; border = &quot;1&quot; > <tr> <td width = &quot;50&quot; align = &quot;right&quot; > 作者 </td> <td><input name = &quot;author&quot; type = &quot;text&quot; size = &quot;8&quot; value = &quot;<%= @post .author%>&quot; /></td> </tr> <tr> <td align = &quot;right&quot; > 標題 </td> <td><input name = &quot;subject&quot; type = &quot;text&quot; size = &quot;40&quot; value = &quot;<%= @post .subject%>&quot; /></td> </tr> <tr> <td align = &quot;right&quot; > 內文 </td> <td><textarea name = &quot;message&quot; cols = &quot;80&quot; rows = &quot;20&quot; > <%= @post .message%> </textarea></td> </tr> <tr> <td align = &quot;right&quot; > &nbsp; </td> <td><input type = &quot;submit&quot; value = &quot; 送出 &quot; /></td> </tr> </table>
  • 285. VIEWS #_post_err.erb <% unless post.errors.blank?%> <ul> <%post.errors.each do |att,msg|%> <li> <%=att%> : <%=msg%> </li> <% end %> </ul> <% end %>
  • 286. VIEWS #index.erb <p><a href = &quot;/posts/new&quot; > 新增 </a></p> <table border = &quot;1&quot; > <tr> <th> ID </th> <th> 刪 </th> <th> 作者 </th> <th> 標題 </th> </tr> <% @posts .each do |post|%> <tr> <td> <%=post.id%> </td> <td><a onclick = &quot;return confirm(' 確定要刪除嗎 ?')&quot; href = &quot;/posts/<%=post.id%>/delete&quot; > DEL </a></td> <td> <%=post.author%> </td> <td><a href = &quot;/posts/<%=post.id%>&quot; > <%=post.subject%> </a></td> </tr> <% end %> </table>
  • 287. VIEWS #show.erb <p><a href = &quot;/posts/<%= @post .id%>/edit&quot; > 修改 </a></p> <table width = &quot;80%&quot; border = &quot;1&quot; > <tr><td width = &quot;50&quot; align = &quot;right&quot; > 作者 </td><td> <%= @post .author%> </td></tr> <tr><td align = &quot;right&quot; > 標題 </td><td> <%= @post .subject%> </td></tr> <tr><td align = &quot;right&quot; > 內文 </td><td> <%= @post .message%> </td></tr> </table>