Pro Yearly is on sale from $80 to $50! »

intro ruby

intro ruby

高达350页的介绍幻灯

6002ee051e03f0b762642ee7fafd111f?s=128

Zoom.Quiet

May 06, 2013
Tweet

Transcript

  1. Ruby 程式語⾔言 綜覽簡介 ihower@gmail.com 2013/4

  2. 我是誰? • 張⽂文鈿 a.k.a. ihower • http://ihower.tw • http://twitter.com/ihower •

    Ruby Developer since 2006 • CTO, Faria Systems Ltd. • The organizer of RubyConf Taiwan • http://rubyconf.tw • http://ruby.tw
  3. Agenda • 什麼是 Ruby • 基本語法 • Ruby 的幾個特點 •

    Ruby 的語⾔言實作 • 各式應⽤用 • ⽣生態圈
  4. 什麼是 Ruby? • 開放原碼、物件導向的動態直譯式 (interpreted)程式語⾔言 • 簡單哲學、⾼高⽣生產⼒力 • 精巧、⾃自然的語法 •

    創造者 Yukihiro Matsumoto, a.k.a. Matz • 靈感來⾃自 Lisp, Perl, 和 Smalltalk • 設計的⺫⽬目的是要讓程式設計師 Happy
  5. Matz@RubyConf Taiwan 2012

  6. ⾺馬斯洛需求層次理論 ⽣生理 安全 社交 尊重 ⾃自我實現 Happy? DHH(Rails creator)

  7. None
  8. None
  9. http://redmonk.com/sogrady/2012/09/12/language-rankings-9-12/ Stackoverflow 和 Github 的熱⾨門排名

  10. None
  11. irb: Interactive Ruby ⾺馬上動⼿手練習 irb(main):001:0> irb(main):001:0> 1 + 1 =>

    2 irb(main):002:0>
  12. PUTS 螢幕輸出 • 打開編輯器,編輯 hello.rb • 執⾏行 ruby number.rb puts

    "Hello World!"
  13. Ruby 是動態強分型語⾔言 • 動態 Dynamic v.s. 靜態 Static typing •

    Ruby/Perl/Python/PHP v.s. Java/C/C++ • 強 Strong v.s. 弱 Weak typing • Ruby/Perl/Python/Java v.s. PHP/C/C++
  14. 什麼強?弱?分型 i=1 puts "Value is " + i #TypeError: can't

    convert Fixnum into String # from (irb):2:in `+' # from (irb):2 $i = 1; echo "Value is " + $i # 1 PHP code: Ruby code: int a = 5; float b = a; C code:
  15. 1. Ruby 基本語法

  16. 整數 Integer 5 -205 9999999999 0

  17. 浮點數 Float 後⾯面有 . 54.321 0.001 -12.312 0.0

  18. 浮點數四則運算 puts 1.0 + 2.0 puts 2.0 * 3.0 puts

    5.0 - 8.0 puts 9.0 / 2.0 # 3.0 # 6.0 # -3.0 # 4.5
  19. 整數四則運算 結果也會是整數 puts 1 + 2 puts 2 * 3

    puts 5 - 8 puts 9 / 2 # 3 # 6 # -1 # 4
  20. 更多運算 puts 5 * (12-8) + -15 puts 98 +

    (59872 / (13*8)) * -52
  21. 字串 String puts 'Hello, world!' puts '' puts 'Good-bye.'

  22. 字串處理 puts 'I like ' + 'apple pie.' puts 'You\'re

    smart!' puts '12' + 12 #<TypeError: can't convert Fixnum into String>
  23. 更多字串⽅方法 var1 = 'stop' var2 = 'foobar' var3 = "aAbBcC"

    puts var1.reverse # 'pots' puts var2.length # 6 puts var3.upcase puts var3.downcase
  24. Ruby 完全地物件導向 每樣東⻄西都是物件,包括字串和數字。 # 輸出 "UPPER" puts "upper".upcase # 輸出

    -5 的絕對值 puts -5.abs # 輸出 Fixnum puts 99.class # 輸出 "Ruby Rocks!" 五次 5.times do puts "Ruby Rocks!" end
  25. ⽅方法呼叫 Methods • 所有東⻄西都是物件(object),可以呼叫物 件的⽅方法,例如字串、整數、浮點數。 • 透過逗點 . 來對物件呼叫⽅方法

  26. 變數 Variable ⼩小寫開頭,偏好單字之間以底線 _ 分隔 composer = 'Mozart' puts composer

    + ' was "da bomb", in his day.' my_composer = 'Beethoven' puts 'But I prefer ' + my_composer + ', personally.'
  27. 型別轉換 Conversions var1 = 2 var2 = '5' puts var1.to_s

    + var2 # 25 puts var1 + var2.to_i # 7 puts 9.to_f / 2 # 4.5
  28. 常數 Constant ⼤大寫開頭 foo = 1 foo = 2 Foo

    = 1 Foo = 2 # (irb):3: warning: already initialized constant Foo RUBY_PLATFORM ENV
  29. nil 表⽰示未設定值、未定義 nil # nil nil.class # NilClass nil.nil? #

    true 42.nil? # false nil == nil # true false == nil # false
  30. 註解 # 偏好均使⽤用單⾏行註解 # this is a comment line #

    this is a comment line =begin This is a comment line This is a comment line =end
  31. 陣列 Array a = [ 1, "cat", 3.14 ] puts

    a[0] # 輸出 1 puts a.size # 輸出 3 a[2] = nil puts a.inspect # 輸出 [1, "cat", nil]
  32. 更多陣列⽅方法 colors = ["red", "blue"] colors.push("black") colors << "white" puts

    colors.join(", ") # red, blue, black, white colors.pop puts colors.last #black
  33. 雜湊 Hash (Associative Array) config = { "foo" => 123,

    "bar" => 456 } puts config["foo"] # 輸出 123
  34. 字串符號 Symbols 唯⼀一且不會變動的識別名稱 config = { :foo => 123, :bar

    => 456 } puts config[:foo] # 輸出 123
  35. 流程控制 Flow Control

  36. ⽐比較⽅方法 puts 1 > 2 puts 1 < 2 puts

    5 >= 5 puts 5 <= 4 puts 1 == 1 puts 2 != 1 puts ( 2 > 1 ) && ( 2 > 3 ) # and puts ( 2 > 1 ) || ( 2 > 3 ) # or
  37. 控制結構 If if account.total > 100000 puts "large account" elsif

    account.total > 25000 puts "medium account" else puts "small account" end
  38. 控制結構 If if account.total > 100000 puts "large account" elsif

    account.total > 25000 puts "medium account" else puts "small account" end Perl Style
  39. 三元運算⼦子 expression ? true_expresion : false_expression x = 3 puts

    ( x > 3 )? "大於三" : "小於或等於三" # 輸出 小於或等於三
  40. 控制結構 Case case name when "John" puts "Howdy John!" when

    "Ryan" puts "Whatz up Ryan!" else puts "Hi #{name}!" end
  41. 迴圈 while, loop, until, next and break i = 0

    loop do i += 1 break if i > 10 # 中斷迴圈 end i=0 while ( i < 10 ) i += 1 next if i % 2 == 0 #跳過雙數 end i = 0 i += 1 until i > 10 puts i # 輸出 11
  42. 真或假 只有 false 和 nil 是假,其他為真 puts "not execute" if

    nil puts "not execute" if false puts "execute" if true # 輸出 execute puts "execute" if “” # 輸出 execute (和JavaScript不同) puts "execute" if 0 # 輸出 execute (和C不同) puts "execute" if 1 # 輸出 execute puts "execute" if "foo" # 輸出 execute puts "execute" if Array.new # 輸出 execute
  43. Regular Expressions 與 Perl 接近的語法 # 抓出⼿手機號碼 phone = "123-456-7890"

    if phone =~ /(\d{3})-(\d{3})-(\d{4})/ ext = $1 city = $2 num = $3 end
  44. ⽅方法定義 Methods def 開頭 end 結尾 def say_hello(name) result =

    "Hi, " + name return result end puts say_hello('ihower') # 輸出 Hi, ihower
  45. ⽅方法定義 Methods def 開頭 end 結尾 def say_hello(name) result =

    "Hi, " + name return result end puts say_hello('ihower') # 輸出 Hi, ihower 字串相加
  46. ⽅方法定義 Methods def 開頭 end 結尾 def say_hello(name) result =

    "Hi, " + name return result end puts say_hello('ihower') # 輸出 Hi, ihower 字串相加 return 可省 略,最後⼀一⾏行 就是回傳值
  47. ? 與 ! 的慣例 ⽅方法名稱可以⽤用?或!結尾,前者表⽰示會回傳 Boolean, 後者暗⽰示會有某種 side-effect。 array=[2,1,3] array.empty?

    # false array.sort # [1,2,3] array.inspect # [2,1,3] array.sort! # [1,2,3] array.inspect # [1,2,3]
  48. 類別 Classes ⼤大寫開頭,使⽤用 new 可以建⽴立出物件 color_string = String.new color_string =

    "" # 等同 color_array = Array.new color_array = [] # 等同 color_hash = Hash.new color_hash = {} # 等同 time = Time.new puts time
  49. 類別 Class class Person def initialize(name) @name = name end

    def say(word) puts "#{word}, #{@name}" end end p1 = Person.new("ihower") p2 = Person.new("ihover") p1.say("Hello") # 輸出 Hello, ihower p2.say("Hello") # 輸出 Hello, ihover
  50. 類別 Class class Person def initialize(name) @name = name end

    def say(word) puts "#{word}, #{@name}" end end p1 = Person.new("ihower") p2 = Person.new("ihover") p1.say("Hello") # 輸出 Hello, ihower p2.say("Hello") # 輸出 Hello, ihover 建構式
  51. 類別 Class class Person def initialize(name) @name = name end

    def say(word) puts "#{word}, #{@name}" end end p1 = Person.new("ihower") p2 = Person.new("ihover") p1.say("Hello") # 輸出 Hello, ihower p2.say("Hello") # 輸出 Hello, ihover 建構式 物件變數
  52. 類別 Class class Person def initialize(name) @name = name end

    def say(word) puts "#{word}, #{@name}" end end p1 = Person.new("ihower") p2 = Person.new("ihover") p1.say("Hello") # 輸出 Hello, ihower p2.say("Hello") # 輸出 Hello, ihover 建構式 物件變數 字串相加
  53. 類別 Class class Person def initialize(name) @name = name end

    def say(word) puts "#{word}, #{@name}" end end p1 = Person.new("ihower") p2 = Person.new("ihover") p1.say("Hello") # 輸出 Hello, ihower p2.say("Hello") # 輸出 Hello, ihover 建構式 物件變數 字串相加 ⼤大寫開頭的 常數
  54. 類別 Class (續) class Person @@name = “ihower” def self.say

    puts @@name end end Person.say # 輸出 Hello, ihower
  55. 類別 Class (續) class Person @@name = “ihower” def self.say

    puts @@name end end Person.say # 輸出 Hello, ihower 類別變數
  56. 類別 Class (續) class Person @@name = “ihower” def self.say

    puts @@name end end Person.say # 輸出 Hello, ihower 類別變數 類別⽅方法
  57. 資料封裝 • 所有的物件變數(@開頭) 、類別變數(@@開頭) , 都是封裝在類別內部,類別外無法存取。 • 需透過定義 public ⽅方法才可以存取到

    class Person def initialize(name) @name = name end end p = Person.new('ihower') p.name => NoMethodError p.name='peny' => NoMethodError
  58. class Person def initialize(name) @name = name end def name

    @name end def name=(name) @name = name end end p = Person.new('ihower') p.name => "ihower" p.name="peny" => "peny"
  59. ⽅方法封裝 預設是 public 公開 class MyClass def public_method end def

    private_method end def protected_method end public :public_method private :private_method protected :proected_method end class MyClass def public_method end private def private_method end protected def protected_method end end
  60. 類別 Class body 也可以執⾏行程式 attr_accessor, attr_writer, attr_reader class Person attr_accessor

    :name end class Person def name @name end def name=(val) @name = val end end 等同於
  61. Class 繼承 class Pet attr_accessor :name, :age end class Cat

    < Pet end class Dog < Pet end
  62. Module (1) Namespace module MyUtil def self.foobar puts "foobar" end

    end MyUtil.foobar # 輸出 foobar
  63. Module(2) Mixins module Debug def who_am_i? "#{self.class.name} (\##{self.object_id}): #{self.to_s}" end

    end class Foo include Debug # 這個動作叫做 Mixin # ... end class Bar include Debug # ... end ph = Foo.new("12312312") et = Bar.new("78678678") ph.who_am_i? # 輸出 "Foo (#330450): 12312312" et.who_am_i? # 輸出 "Bar (#330420): 78678678"
  64. Module(2) Mixins module Debug def who_am_i? "#{self.class.name} (\##{self.object_id}): #{self.to_s}" end

    end class Foo include Debug # 這個動作叫做 Mixin # ... end class Bar include Debug # ... end ph = Foo.new("12312312") et = Bar.new("78678678") ph.who_am_i? # 輸出 "Foo (#330450): 12312312" et.who_am_i? # 輸出 "Bar (#330420): 78678678" Ruby 使⽤用 Module 來解決 多重繼承問題
  65. ⾛走訪迴圈 each method languages = ['Ruby', 'Javascript', 'Perl'] languages.each do

    |lang| puts 'I love ' + lang + '!' end # I Love Ruby # I Love Javascript # I Love Perl
  66. 迭代器 iterator • 不同於 while 迴圈⽤用法,each 是⼀一個陣 列的⽅方法,⾛走訪其中的元素,我們稱作 迭代器(iterator) •

    其中 do .... end 是 each ⽅方法的參數,稱 作匿名⽅方法( code block)
  67. 最簡單的迭代器 3.times do puts 'Good Job!' end # Good Job!

    # Good Job! # Good Job!
  68. code block ⼀一種匿名⽅方法,或稱作 closure { puts "Hello" } # 這是一個

    block do puts "Blah" # 這也是一個 block puts "Blah" end
  69. code block 內部迭代器(iterator) # 處理陣列 people people = ["David", "John",

    "Mary"] people.each do |person| puts person end # 反覆五次 5.times { puts "Ruby rocks!" } # 從一數到九 1.upto(9) { |x| puts x }
  70. code block 內部迭代器(iterator) # 處理陣列 people people = ["David", "John",

    "Mary"] people.each do |person| puts person end # 反覆五次 5.times { puts "Ruby rocks!" } # 從一數到九 1.upto(9) { |x| puts x } 所以我們將 很少⽤用到 while, until, for 等迴圈
  71. code block 其他迭代⽅方式 # 迭代並造出另一個陣列 a = [ "a", "b",

    "c", "d" ] b = a.map {|x| x + "!" } puts b.inspect # 結果是 ["a!", "b!", "c!", "d!"] # 找出符合條件的值 b = [1,2,3].find_all{ |x| x % 2 == 0 } b.inspect # 結果是 [2]
  72. code block 當作判斷條件 # 迭代並根據條件刪除 a = [ "a", "b",

    "c" ] a.delete_if {|x| x >= "b" } # 結果是 ["a"] # 客製化排序 [2,1,3].sort! { |a, b| b <=> a } # 結果是 ["3",”2”,”1”]
  73. code block 有沒有 functional programming 的 fu? # 計算總和 (5..10).inject

    {|sum, n| sum + n } # 找出最長字串find the longest word longest = ["cat", "sheep", "bear"].inject do |memo, word| ( memo.length > word.length )? memo : word end
  74. code block 僅執⾏行⼀一次呼叫 file = File.new("testfile", "r") # ...處理檔案 file.close

    File.open("testfile", "r") do |file| # ...處理檔案 end # 檔案自動關閉
  75. Yield 在⽅方法中使⽤用 yield 來執⾏行 code block # 定義方法 def call_block

    puts "Start" yield yield puts "End" end call_block { puts "Blocks are cool!" } # 輸出 # "Start" # "Blocks are cool!" # "Blocks are cool!" # "End"
  76. 帶參數的 code block def call_block yield(1) yield(2) yield(3) end call_block

    { |i| puts "#{i}: Blocks are cool!" } # 輸出 # "1: Blocks are cool!" # "2: Blocks are cool!" # "3: Blocks are cool!"
  77. Proc object 將 code block 明確轉成物件 def call_block(&block) block.call(1) block.call(2)

    block.call(3) end call_block { |i| puts "#{i}: Blocks are cool!" } # 或是先宣告出 proc object proc_1 = Proc.new { |i| puts "#{i}: Blocks are cool!" } proc_2 = lambda { |i| puts "#{i}: Blocks are cool!" } call_block(&proc_1) call_block(&proc_2) # 輸出 # "1: Blocks are cool!" # "2: Blocks are cool!" # "3: Blocks are cool!"
  78. 傳遞不定參數 def my_sum(*val) val.inject(0) { |sum, v| sum + v

    } end puts my_sum(1,2,3,4) # 輸出 10
  79. 參數尾 Hash 可省略 { } def my_print(a, b, options) puts

    a puts b puts options[:x] puts options[:y] puts options[:z] end my_print("A", "B", { :x => 123, :z => 456 } ) my_print("A", "B", :x => 123, :z => 456) # 結果相同 # 輸出 A # 輸出 B # 輸出 123 # 輸出 nil # 輸出 456
  80. 例外處理 raise, begin, rescue, ensure begin puts 10 / 0

    rescue => e puts e.class ensure # ... end # 輸出 ZeroDivisionError raise "Not works!!" # 丟出一個 RuntimeError # 自行自定例外物件 class MyException < RuntimeError end raise MyException
  81. 2. Ruby 的特點 Ruby supports multiple programming paradigms

  82. 1. Object-Oriented 物件導向程式設計

  83. Everything in Ruby is object, even class.

  84. Ruby Object Model class A end class B < A

    end obj = B.new obj.class # B B.superclass # A B.class # Class obj B Object Class A class class super super
  85. class object is an object of the class Class obj

    B Object Class A class class super super class class class class A end class B < A end obj = B.new obj.class # B B.superclass # A B.class # Class
  86. class A end module B end module C end class

    D < A include B include C end D.ancestors => [D, C, B, A, Object, Kernel, BasicObject] module obj D A Mixin B,C class super super
  87. class A def foo end end obj1 = A.new obj2

    = A.new what’s metaclass? obj2 Object A class super obj2 class
  88. obj2 Object A class super obj2’s metaclass obj2 class super

    class A def foo end end obj1 = A.new obj2 = A.new def obj2.bar # only obj2 has bar method, # called singleton method end # another way class << obj1 def baz #only obj1 has baz method end end P.S. well, number and symbol have no metaclass metaclass also known as singleton, eigenclass, ghost class, virtual class. every object has his own metaclass
  89. A A’s metaclass super Class class B class class A

    # way1 def self.foo end # way2 class << self def bar end end end # way3 def A.baz end A.foo A.bar A.baz class object has its metaclass too. so the singleton method is class method!!
  90. 動態型別 (duck typing) 會聒聒叫的就是鴨⼦子 # 鴨子 class Duck def quack

    puts "quack!" end end # 野鴨 (不用繼承) class Mallard def quack puts "qwuaacck!! quak!" end end
  91. Class 不是 Type ⼀一個物件可以做什麼才是重點 birds = [Duck.new, Mallard.new, Object.new] #

    迭代陣列,並呼叫方法 (無須擔心型別) birds.each do |duck| duck.quack if duck.respond_to? :quack end
  92. Duck Typing (from wikipedia) • duck typing is a style

    of dynamic typing in which an object's methods and properties determine the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface
  93. prototype-based programming Like JavaScript, Ruby can do, too Animal =

    Object.new def Animal.run end def Animal.sit end Cat = Animal.clone Cat.run Dog = Animal.clone Dog.run
  94. class-oriented programming v.s. object-oriented programming http://stackoverflow.com/questions/546670/what-is-the-difference-between-class- oriented-and-object-oriented-programming

  95. “With Ruby, you can think in terms of classes or

    in terms of objects. With Javascript, you can think in terms of prototypes or in terms of objects. With Java and C++, classes are your only option.” by Giles Bowkett
  96. 2. Functional Programming 函數式程式設計 http://www.slideshare.net/ihower/fp-osdc2012v2 https://github.com/JuanitoFatas/Ruby-Functional-Programming

  97. (1) Higher-Order Functions tickets = { "a" => 1100, "b"

    => 900, "c" => 800 } highest_price = 0 tickets.each do |ticket, price| if price < 1000 highest_price = price if price > highest_price end end highest_price # 900
  98. Higher-Order Functions (cont.) tickets = { "a" => 1100, "b"

    => 900, "c" => 800 } tickets.map{ |x| x[1] }.select{ |x| x < 1000 }.max # 900
  99. pre- and Post-processing usage example f = File.open("myfile.txt", 'w') f.write("Lorem

    ipsum dolor sit amet") f.write("Lorem ipsum dolor sit amet") f.close # using block File.open("myfile.txt", 'w') do |f| f.write("Lorem ipsum dolor sit amet") f.write("Lorem ipsum dolor sit amet") end
  100. Dynamic Callbacks Sinatra usage example get '/posts' do #.. show

    something .. end post '/posts' do #.. create something .. end put '/posts/:id' do #.. update something .. end delete '/posts/:id' do #.. annihilate something .. end
  101. Dynamic Callbacks server = Server.new server.handle(/hello/) do puts "Hello at

    #{Time.now}" end server.handle(/goodbye/) do puts "goodbye at #{Time.now}" end server.execute("/hello") # Hello at Wed Apr 21 17:33:31 +0800 2010 server.execute("/goodbye") # goodbye at Wed Apr 21 17:33:42 +0800 2010
  102. class Server def initialize @handlers = {} end def handle(pattern,

    &block) @handlers[pattern] = block end def execute(url) @handlers.each do |pattern, block| if match = url.match(pattern) block.call break end end end end
  103. (2) Everything is an expression if found_dog == our_dog name

    = found_dog.name message = "We found our dog #{name}!" else message = "No luck" end
  104. Everything is an expression (cont.) message = if found_dog ==

    my_dog name = found_dog.name "We found our dog #{name}!" else "No luck" end
  105. (3) Lazy enumerators require 'prime' Prime.to_a # 這樣是無窮數列... Prime.take(10).to_a #

    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] Prime.lazy.select{ |x| x % 4 == 3 }.take(10).to_a # => [3, 7, 11, 19, 23, 31, 43, 47, 59, 67]
  106. 3. Metaprogramming ⽤用程式寫程式 http://ihower.tw/blog/archives/4279

  107. Two types of meta- programming • Code Generation • eg.

    Rails scaffold • Reflection • eg. Class Macro
  108. Class Bodies Aren’t Special class Demo a = 1 puts

    a def self.say puts "blah" end say # you can execute class method in class body end # 1 # blah
  109. Introspection (反射機制) # 這個物件有什麼方法 Object.methods => ["send", "name", "class_eval", "object_id",

    "new", "singleton_methods", ...] # 這個物件有這個方法嗎? Object.respond_to? :name => true
  110. define_method 動態定義⽅方法 class Dragon define_method(:foo) { puts "bar" } ['a','b','c','d','e','f'].each

    do |x| define_method(x) { puts x } end end dragon = Dragon.new dragon.foo # 輸出 "bar" dragon.a # 輸出 "a" dragon.f # 輸出 "f"
  111. Rails example class Firm < ActiveRecord::Base has_many :clients has_one :account

    belongs_to :conglomorate end # has_many 是 AciveRecord 的 class method # 其內容是動態定義出 Firm 的一堆 instance methods firm = Firm.find(1) firm.clients firm.clients.size firm.clients.build firm.clients.destroy_all
  112. Memorize example (Class Macro) class Account def calculate @calculate ||=

    begin sleep 10 # expensive calculation 5 end end end a = Account.new a.caculate # need waiting 10s to get 5 a.caculate # 5 a.caculate # 5 a.caculate # 5
  113. memoize method class Account def calculate sleep 2 # expensive

    calculation 5 end memoize :calculate end a = Account.new a.calculate # need waiting 10s to get 5 a.calculate # 5
  114. class Class def memoize(name) original_method = "_original_#{name}" alias_method :"#{original_method}", name

    define_method name do cache = instance_variable_get("@#{name}") if cache return cache else result = send(original_method) # Dynamic Dispatches instance_variable_set("@#{name}", result) return result end end end end
  115. It’s general for any class class Car def run sleep

    100 # expensive calculation “done” end memoize :run end c = Car.new c.run # need waiting 100s to get done c.run # done
  116. Method Missing car = Car.new car.go_to_taipei # go to taipei

    car.go_to_shanghai # go to shanghai car.go_to_japan # go to japan
  117. class Car def go(place) puts "go to #{place}" end def

    method_missing(name, *args) if name.to_s =~ /^go_to_(.*)/ go($1) else super end end end car = Car.new car.go_to_taipei # go to taipei car.blah # NoMethodError: undefined method `blah`
  118. XML builder example builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) builder.person do |b|

    b.name("Jim") b.phone("555-1234") b.address("Taipei, Taiwan") end # <person> # <name>Jim</name> # <phone>555-1234</phone> # <address>Taipei, Taiwan</address> # </person>
  119. DSL (Domain-Specific Language) • Internal DSL • 沿⽤用程式語⾔言本⾝身的 Syntax •

    Ruby 有⾮非常好的能⼒力可以作為 Internal DSL 之⽤用 • External DSL • ⾃自⾏行發明 Syntax,再⽤用程式語⾔言去解析
  120. 4. Encodings http://ihower.tw/blog/archives/2722

  121. UCS v.s. CSI • UCS (Universal Character Set) • 語⾔言內部統⼀一轉換成使⽤用

    UTF-16 或 UTF-8,Java/Python/Perl 等⼤大部分語⾔言 都這樣做 • CSI (Character Set Independent) • Ruby 內建⽀支援 99 種 Encodings,並不 做轉換
  122. pick one encoding, likely Unicode, and works all data in

    one format? No. Ruby 1.9 make it possible to work with data with 99 encoding.
  123. 1.9.3-p392 :024 > Encoding.name_list => ["ASCII-8BIT", "UTF-8", "US-ASCII", "Big5", "Big5-HKSCS",

    "Big5-UAO", "CP949", "Emacs-Mule", "EUC-JP", "EUC-KR", "EUC-TW", "GB18030", "GBK", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "KOI8-R", "KOI8-U", "Shift_JIS", "UTF-16BE", "UTF-16LE", "UTF-32BE", "UTF-32LE", "Windows-1251", "BINARY", "IBM437", "CP437", "IBM737", "CP737", "IBM775", "CP775", "CP850", "IBM850", "IBM852", "CP852", "IBM855", "CP855", "IBM857", "CP857", "IBM860", "CP860", "IBM861", "CP861", "IBM862", "CP862", "IBM863", "CP863", "IBM864", "CP864", "IBM865", "CP865", "IBM866", "CP866", "IBM869", "CP869", "Windows-1258", "CP1258", "GB1988", "macCentEuro", "macCroatian", "macCyrillic", "macGreek", "macIceland", "macRoman", "macRomania", "macThai", "macTurkish", "macUkraine", "CP950", "Big5-HKSCS:2008", "CP951", "stateless-ISO-2022- JP", "eucJP", "eucJP-ms", "euc-jp-ms", "CP51932", "eucKR", "eucTW", "GB2312", "EUC- CN", "eucCN", "GB12345", "CP936", "ISO-2022-JP", "ISO2022-JP", "ISO-2022-JP-2", "ISO2022-JP2", "CP50220", "CP50221", "ISO8859-1", "Windows-1252", "CP1252", "ISO8859-2", "Windows-1250", "CP1250", "ISO8859-3", "ISO8859-4", "ISO8859-5", "ISO8859-6", "Windows-1256", "CP1256", "ISO8859-7", "Windows-1253", "CP1253", "ISO8859-8", "Windows-1255", "CP1255", "ISO8859-9", "Windows-1254", "CP1254", "ISO8859-10", "ISO8859-11", "TIS-620", "Windows-874", "CP874", "ISO8859-13", "Windows-1257", "CP1257", "ISO8859-14", "ISO8859-15", "ISO8859-16", "CP878", "Windows-31J", "CP932", "csWindows31J", "SJIS", "PCK", "MacJapanese", "MacJapan", "ASCII", "ANSI_X3.4-1968", "646", "UTF-7", "CP65000", "CP65001", "UTF8-MAC", "UTF-8- MAC", "UTF-8-HFS", "UTF-16", "UTF-32", "UCS-2BE", "UCS-4BE", "UCS-4LE", "CP1251", "UTF8-DoCoMo", "SJIS-DoCoMo", "UTF8-KDDI", "SJIS-KDDI", "ISO-2022-JP-KDDI", "stateless-ISO-2022-JP-KDDI", "UTF8-SoftBank", "SJIS-SoftBank", "locale", "external", "filesystem", "internal"]
  124. All String are Encoded • In Ruby 1.9 a String

    is a collection of encoded characters. 除了 raw bytes,還包括 Encoding 資訊。 >> "中文".encoding.name => "UTF-8" Encoding object
  125. In Ruby 1.9, String has attached Encoding object, and works

    in characters.
  126. Transcoding 改變編碼 utf8 = "測試" utf8.bytesize # 6 utf8.bytes.to_a #

    [230, 184, 172, 232, 169, 166] big5 = utf8.encode("big5") big5.encoding.name # ”Big5” big5.bytesize # 4 big5.bytes.to_a # [180, 250, 184, 213]
  127. Transcoding fails 轉碼失敗 str = "Résumé" str.encode("big5") => Encoding::UndefinedConversionError: "\xC3\xA9"

    from UTF-8 to Big5 from (irb):2:in `encode' from (irb):2 from /usr/local/bin/irb19:12:in `<main>'
  128. Force Transcoding 改變編碼,但不改 byte data utf8 = "測試" big5 =

    utf8.encode("big5") big5.valid_encoding? => true big5.force_encoding("utf-8") big5.valid_encoding? => false
  129. Force Transcoding fails 編碼不對無法進⼀一步操作 big5.valid_encoding? # false big5 =~ /123456/

    => ArgumentError: invalid byte sequence in UTF-8 from (irb):11 from /usr/local/bin/irb19:12:in `<main>'
  130. Encoding.compatible? 例如: ASCII with a bigger Encoding ascii = "my

    ".force_encoding("ascii") utf8 = "Résumé" # 檢查相容性 Encoding.compatible?(ascii, utf8) #<Encoding:UTF-8> # 相加 my_resume = ascii + utf8 puts my_resume # "My Résumé" puts my_resume.encoding.name # UTF-8
  131. Encoding.compatible? 不相容不能加在⼀一起 big5 = "測試".encode("big5") utf8 = "Résumé" # 檢查相容性

    Encoding.compatible?(big5, utf8) # nil # 相加 big5 + utf8 => Encoding::CompatibilityError: incompatible character encodings: Big5 and UTF-8 from (irb):25 from /usr/local/bin/irb19:12:in `<main>'
  132. 3. Ruby 的實作

  133. 程式語⾔言和程式語⾔言的實作, 是兩回事 (雖然很多語⾔言只有⼀一種實作) 程式語⾔言本⾝身沒有效能快慢,程式語⾔言的實作才有

  134. CRuby / MRI (Matz's Ruby Interpreter) • 1.8.7 is dead

    • 1.9.3 • 2.0 is released at 2/24/2013 (⼆二⼗十週年)
  135. JRuby

  136. Rubinius

  137. Concurrency models 的爭論 • process-based • CRuby has GVL (global

    VM lock) • thread-based • reactor pattern • eventmachine (Ruby library) • node.js (JavaScript)
  138. IronRuby

  139. MacRuby

  140. RubyMotion

  141. mruby

  142. 4. Ruby 的應⽤用 how ruby change the world!

  143. Web framework • MVC • ORM • URL Routing •

    View Template
  144. None
  145. None
  146. Web Designer Tools • Sass/Less/Haml • Compass

  147. Testing/BDD Ruby community loves testing • RSpec • Cucumber http://ihower.tw/blog/archives/5438

    http://ihower.tw/blog/archives/5983
  148. What’s BDD? • An improved xUnit Framework • Focus on

    clearly describe the expected behavior • The emphasis is Tests as Documentation rather than merely using tests for verification.
  149. Terminology changed New paradigm: Executable Specification • “Test” becomes “Spec”

    • “Assertion” becomes “Expectation” • “test method” becomes “example” (RSpec) • “test case” becomes “example group” (RSpec)
  150. None
  151. class OrderTest < Test::Unit::TestCase def setup @order = Order.new end

    def test_order_status_when_initialized assert_equal @order.status, "New" end def test_order_amount_when_initialized assert_equal @order.amount, 0 end end Test::Unit 寫法
  152. describe Order do before do @order = Order.new end context

    "when initialized" do it "should have default status is New" do @order.status.should == "New" end it "should have default amount is 0" do @order.amount.should == 0 end end end RSpec 寫法
  153. None
  154. DevOps • Chef • Puppet • Vagrant

  155. None
  156. None
  157. None
  158. Mac

  159. Mac

  160. Blogging (static HTML generator)

  161. Redmine

  162. 5. Ruby ⽣生態圈

  163. 1. Editors & IDEs

  164. None
  165. None
  166. Vim for Rails

  167. Emacs for Rails

  168. 2. Web Services & Monitors

  169. None
  170. None
  171. None
  172. 3.Hosting

  173. 3.a PaaS (Platform as a Service)

  174. None
  175. None
  176. 3.b ⾼高C/P值的 VPS (Virtual Private Server)

  177. None
  178. None
  179. 3.b IaaS (Infrastructure as a service) Cloud Hosing

  180. None
  181. None
  182. 4. Consulting

  183. None
  184. None
  185. None
  186. None
  187. None
  188. http://www.workingwithrails.com/

  189. None
  190. None
  191. 5. Conferences

  192. None
  193. None
  194. None
  195. None
  196. None
  197. None
  198. None
  199. None
  200. 6. Books

  201. None
  202. None
  203. http://www.pragprog.com/

  204. None
  205. None
  206. None
  207. None
  208. None
  209. None
  210. 閱讀練習時,⼩小⼼心 Rails 版本差異 1.2, 2.0, 2.1, 2.2, 2.3, 3.0, 3,1,

    3.2 4.0 書籍尚未上市
  211. http://guides.rubyonrails.org/

  212. None
  213. None
  214. 7. Video

  215. http://peepcode.com/

  216. None
  217. 8. Website & Blog (free)

  218. http://weblog.rubyonrails.org/

  219. http://www.rubyinside.com/

  220. http://ruby5.envylabs.com

  221. http://railscasts.com/

  222. http://www.rubyflow.com/

  223. None
  224. http://github.com/

  225. 9. Ruby Community in Taiwan

  226. None
  227. None
  228. None
  229. None
  230. Ruby Tuesday 聚會

  231. None
  232. None
  233. ptt.cc #Ruby 版

  234. http://railsfun.tw/

  235. Thank you. 參考資料: Beginning Ruby 2nd. (Apress) Programming Ruby (The

    Pragmatic Programmers) The Well-Grounded Rubyist (Manning) Ruby 程式設計 (O’Reilly) Foundation Rails 2 (friendsof) http://rubyonrails.org/ecosystem http://infoether.com/ruby-and-rails-whitepaper