Ruby 程式語言綜覽簡介

240
Ruby 程式語 綜覽簡介 [email protected] 2013/4
  • date post

    11-Sep-2014
  • Category

    Technology

  • view

    50
  • download

    14

description

 

Transcript of Ruby 程式語言綜覽簡介

Page 2: Ruby 程式語言綜覽簡介

我是誰?• 張⽂文鈿 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

Page 3: Ruby 程式語言綜覽簡介

Agenda

• 什麼是 Ruby

• 基本語法• Ruby 的幾個特點

• Ruby 的語⾔言實作

• 各式應⽤用• ⽣生態圈

Page 4: Ruby 程式語言綜覽簡介

什麼是 Ruby?

• 開放原碼、物件導向的動態直譯式(interpreted)程式語⾔言

• 簡單哲學、⾼高⽣生產⼒力• 精巧、⾃自然的語法• 創造者 Yukihiro Matsumoto, a.k.a. Matz

• 靈感來⾃自 Lisp, Perl, 和 Smalltalk

• 設計的⺫⽬目的是要讓程式設計師 Happy

Page 5: Ruby 程式語言綜覽簡介

Matz@RubyConf Taiwan 2012

Page 6: Ruby 程式語言綜覽簡介

⾺馬斯洛需求層次理論

⽣生理

安全

社交

尊重

⾃自我實現

Happy?

DHH(Rails creator)

Page 7: Ruby 程式語言綜覽簡介
Page 8: Ruby 程式語言綜覽簡介
Page 9: Ruby 程式語言綜覽簡介

http://redmonk.com/sogrady/2012/09/12/language-rankings-9-12/

Stackoverflow 和Github 的熱⾨門排名

Page 10: Ruby 程式語言綜覽簡介
Page 11: Ruby 程式語言綜覽簡介

irb: Interactive Ruby⾺馬上動⼿手練習

irb(main):001:0>

irb(main):001:0> 1 + 1=> 2

irb(main):002:0>

Page 12: Ruby 程式語言綜覽簡介

PUTS 螢幕輸出

• 打開編輯器,編輯 hello.rb

• 執⾏行 ruby hello.rb

puts "Hello World!"

Page 13: Ruby 程式語言綜覽簡介

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++

Page 14: Ruby 程式語言綜覽簡介

什麼強?弱?分型

i=1puts "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:

Page 15: Ruby 程式語言綜覽簡介

1. Ruby 基本語法

Page 16: Ruby 程式語言綜覽簡介

整數 Integer

5-20599999999990

Page 17: Ruby 程式語言綜覽簡介

浮點數 Float後⾯面有 .

54.3210.001-12.3120.0

Page 18: Ruby 程式語言綜覽簡介

浮點數四則運算puts 1.0 + 2.0puts 2.0 * 3.0puts 5.0 - 8.0puts 9.0 / 2.0

# 3.0# 6.0# -3.0# 4.5

Page 19: Ruby 程式語言綜覽簡介

整數四則運算結果也會是整數

puts 1 + 2puts 2 * 3puts 5 - 8puts 9 / 2

# 3# 6# -1# 4

Page 20: Ruby 程式語言綜覽簡介

更多運算

puts 5 * (12-8) + -15puts 98 + (59872 / (13*8)) * -52

Page 21: Ruby 程式語言綜覽簡介

字串 String

puts 'Hello, world!'puts ''puts 'Good-bye.'

Page 22: Ruby 程式語言綜覽簡介

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

puts '12' + 12 #<TypeError: can't convert Fixnum into String>

Page 23: Ruby 程式語言綜覽簡介

更多字串⽅方法var1 = 'stop'var2 = 'foobar'var3 = "aAbBcC"

puts var1.reverse # 'pots'puts var2.length # 6puts var3.upcaseputs var3.downcase

Page 24: Ruby 程式語言綜覽簡介

Ruby 完全地物件導向每樣東⻄西都是物件,包括字串和數字。

# 輸出 "UPPER"puts "upper".upcase # 輸出 -5 的絕對值puts -5.abs

# 輸出 Fixnumputs 99.class # 輸出 "Ruby Rocks!" 五次5.times do puts "Ruby Rocks!"end

Page 25: Ruby 程式語言綜覽簡介

⽅方法呼叫 Methods

• 所有東⻄西都是物件(object),可以呼叫物件的⽅方法,例如字串、整數、浮點數。

• 透過逗點 . 來對物件呼叫⽅方法

Page 26: Ruby 程式語言綜覽簡介

變數 Variable⼩小寫開頭,偏好單字之間以底線 _ 分隔

composer = 'Mozart'puts composer + ' was "da bomb", in his day.'

my_composer = 'Beethoven'puts 'But I prefer ' + my_composer + ', personally.'

Page 27: Ruby 程式語言綜覽簡介

型別轉換 Conversions

var1 = 2var2 = '5'

puts var1.to_s + var2 # 25puts var1 + var2.to_i # 7

puts 9.to_f / 2 # 4.5

Page 28: Ruby 程式語言綜覽簡介

常數 Constant⼤大寫開頭

foo = 1foo = 2

Foo = 1Foo = 2 # (irb):3: warning: already initialized constant Foo

RUBY_PLATFORMENV

Page 29: Ruby 程式語言綜覽簡介

nil表⽰示未設定值、未定義

nil # nilnil.class # NilClass

nil.nil? # true42.nil? # false

nil == nil # truefalse == nil # false

Page 30: Ruby 程式語言綜覽簡介

註解 #偏好均使⽤用單⾏行註解

# this is a comment line# this is a comment line

=begin This is a comment line This is a comment line=end

Page 31: Ruby 程式語言綜覽簡介

陣列 Arraya = [ 1, "cat", 3.14 ]

puts a[0] # 輸出 1puts a.size # 輸出 3

a[3] = nilputs a.inspect # 輸出字串 [1, "cat", nil]

Page 32: Ruby 程式語言綜覽簡介

更多陣列⽅方法colors = ["red", "blue"]

colors.push("black")colors << "white"puts colors.join(", ") # red, blue, black, white

colors.popputs colors.last #black

Page 33: Ruby 程式語言綜覽簡介

雜湊 Hash(Associative Array)

config = { "foo" => 123, "bar" => 456 }

puts config["foo"] # 輸出 123

Page 34: Ruby 程式語言綜覽簡介

字串符號 Symbols唯⼀一且不會變動的識別名稱

config = { :foo => 123, :bar => 456 }

puts config[:foo] # 輸出 123

Page 35: Ruby 程式語言綜覽簡介

流程控制 Flow Control

Page 36: Ruby 程式語言綜覽簡介

⽐比較⽅方法puts 1 > 2puts 1 < 2puts 5 >= 5puts 5 <= 4puts 1 == 1puts 2 != 1

puts ( 2 > 1 ) && ( 2 > 3 ) # andputs ( 2 > 1 ) || ( 2 > 3 ) # or

Page 37: Ruby 程式語言綜覽簡介

控制結構 If

if account.total > 100000 puts "large account"elsif account.total > 25000 puts "medium account"else puts "small account"end

Page 38: Ruby 程式語言綜覽簡介

控制結構 If

if account.total > 100000 puts "large account"elsif account.total > 25000 puts "medium account"else puts "small account"end

Perl Style

Page 39: Ruby 程式語言綜覽簡介

三元運算⼦子expression ? true_expresion : false_expression

x = 3puts ( x > 3 )? "大於三" : "小於或等於三"

# 輸出 小於或等於三

Page 40: Ruby 程式語言綜覽簡介

控制結構 Case

case name when "John" puts "Howdy John!" when "Ryan" puts "Whatz up Ryan!" else puts "Hi #{name}!"end

Page 41: Ruby 程式語言綜覽簡介

迴圈while, loop, until, next and break

i = 0loop do i += 1 break if i > 10 # 中斷迴圈

end

i=0while ( i < 10 ) i += 1 next if i % 2 == 0 #跳過雙數

end

i = 0i += 1 until i > 10puts i# 輸出 11

Page 42: Ruby 程式語言綜覽簡介

真或假只有 false 和 nil 是假,其他為真

puts "not execute" if nilputs "not execute" if false

puts "execute" if true # 輸出 executeputs "execute" if “” # 輸出 execute (和JavaScript不同)puts "execute" if 0 # 輸出 execute (和C不同)puts "execute" if 1 # 輸出 executeputs "execute" if "foo" # 輸出 executeputs "execute" if Array.new # 輸出 execute

Page 43: Ruby 程式語言綜覽簡介

Regular Expressions與 Perl 接近的語法

# 抓出⼿手機號碼 phone = "123-456-7890" if phone =~ /(\d{3})-(\d{3})-(\d{4})/ ext = $1 city = $2 num = $3end

Page 44: Ruby 程式語言綜覽簡介

⽅方法定義 Methodsdef 開頭 end 結尾

def say_hello(name) result = "Hi, " + name return resultend

puts say_hello('ihower')# 輸出 Hi, ihower

Page 45: Ruby 程式語言綜覽簡介

⽅方法定義 Methodsdef 開頭 end 結尾

def say_hello(name) result = "Hi, " + name return resultend

puts say_hello('ihower')# 輸出 Hi, ihower

字串相加

Page 46: Ruby 程式語言綜覽簡介

⽅方法定義 Methodsdef 開頭 end 結尾

def say_hello(name) result = "Hi, " + name return resultend

puts say_hello('ihower')# 輸出 Hi, ihower

字串相加

return 可省略,最後⼀一⾏行就是回傳值

Page 47: Ruby 程式語言綜覽簡介

? 與 ! 的慣例⽅方法名稱可以⽤用?或!結尾,前者表⽰示會回傳 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]

Page 48: Ruby 程式語言綜覽簡介

類別 Classes⼤大寫開頭,使⽤用 new 可以建⽴立出物件

color_string = String.new color_string = "" # 等同

color_array = Array.newcolor_array = [] # 等同

color_hash = Hash.newcolor_hash = {} # 等同

time = Time.newputs time

Page 49: Ruby 程式語言綜覽簡介

類別 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, ihowerp2.say("Hello") # 輸出 Hello, ihover

Page 50: Ruby 程式語言綜覽簡介

類別 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, ihowerp2.say("Hello") # 輸出 Hello, ihover

建構式

Page 51: Ruby 程式語言綜覽簡介

類別 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, ihowerp2.say("Hello") # 輸出 Hello, ihover

建構式

物件變數

Page 52: Ruby 程式語言綜覽簡介

類別 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, ihowerp2.say("Hello") # 輸出 Hello, ihover

建構式

物件變數

字串相加

Page 53: Ruby 程式語言綜覽簡介

類別 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, ihowerp2.say("Hello") # 輸出 Hello, ihover

建構式

物件變數

字串相加

⼤大寫開頭的常數

Page 54: Ruby 程式語言綜覽簡介

類別 Class (續)

class Person

@@name = “ihower” def self.say puts @@name end end

Person.say # 輸出 Hello, ihower

Page 55: Ruby 程式語言綜覽簡介

類別 Class (續)

class Person

@@name = “ihower” def self.say puts @@name end end

Person.say # 輸出 Hello, ihower

類別變數

Page 56: Ruby 程式語言綜覽簡介

類別 Class (續)

class Person

@@name = “ihower” def self.say puts @@name end end

Person.say # 輸出 Hello, ihower

類別變數

類別⽅方法

Page 57: Ruby 程式語言綜覽簡介

資料封裝• 所有的物件變數(@開頭)、類別變數(@@開頭),都是封裝在類別內部,類別外無法存取。

• 需透過定義 public ⽅方法才可以存取到class Person def initialize(name) @name = name endend

p = Person.new('ihower')p.name => NoMethodErrorp.name='peny' => NoMethodError

Page 58: Ruby 程式語言綜覽簡介

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"

Page 59: Ruby 程式語言綜覽簡介

⽅方法封裝預設是 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

Page 60: Ruby 程式語言綜覽簡介

類別 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

等同於

Page 61: Ruby 程式語言綜覽簡介

Class 繼承class Pet attr_accessor :name, :ageend

class Cat < Petend

class Dog < Petend

Page 62: Ruby 程式語言綜覽簡介

Module (1) Namespacemodule MyUtil

def self.foobar puts "foobar" end end

MyUtil.foobar# 輸出 foobar

Page 63: Ruby 程式語言綜覽簡介

Module(2) Mixinsmodule Debug def who_am_i? "#{self.class.name} (\##{self.object_id}): #{self.to_s}" endend

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"

Page 64: Ruby 程式語言綜覽簡介

Module(2) Mixinsmodule Debug def who_am_i? "#{self.class.name} (\##{self.object_id}): #{self.to_s}" endend

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 來解決多重繼承問題

Page 65: Ruby 程式語言綜覽簡介

⾛走訪迴圈 each method

languages = ['Ruby', 'Javascript', 'Perl']

languages.each do |lang| puts 'I love ' + lang + '!'end

# I Love Ruby# I Love Javascript# I Love Perl

Page 66: Ruby 程式語言綜覽簡介

迭代器 iterator

• 不同於 while 迴圈⽤用法,each 是⼀一個陣列的⽅方法,⾛走訪其中的元素,我們稱作迭代器(iterator)

• 其中 do .... end 是 each ⽅方法的參數,稱作匿名⽅方法( code block)

Page 67: Ruby 程式語言綜覽簡介

最簡單的迭代器3.times do puts 'Good Job!'end

# Good Job!# Good Job!# Good Job!

Page 68: Ruby 程式語言綜覽簡介

code block⼀一種匿名⽅方法,或稱作 closure

{ puts "Hello" } # 這是一個 block

do puts "Blah" # 這也是一個 block puts "Blah"end

Page 69: Ruby 程式語言綜覽簡介

code block內部迭代器(iterator)

# 處理陣列 people

people = ["David", "John", "Mary"]people.each do |person| puts personend # 反覆五次

5.times { puts "Ruby rocks!" }

# 從一數到九

1.upto(9) { |x| puts x }

Page 70: Ruby 程式語言綜覽簡介

code block內部迭代器(iterator)

# 處理陣列 people

people = ["David", "John", "Mary"]people.each do |person| puts personend # 反覆五次

5.times { puts "Ruby rocks!" }

# 從一數到九

1.upto(9) { |x| puts x }

所以我們將很少⽤用到

while, until, for 等迴圈

Page 71: Ruby 程式語言綜覽簡介

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]

Page 72: Ruby 程式語言綜覽簡介

code block當作判斷條件

# 迭代並根據條件刪除

a = [ "a", "b", "c" ]a.delete_if {|x| x >= "b" }# 結果是 ["a"]

# 客製化排序

[2,1,3].sort! { |a, b| b <=> a }# 結果是 [3, 2, 1]

Page 73: Ruby 程式語言綜覽簡介

code block有沒有 functional programming 的 fu?

# 計算總和

(5..10).inject {|sum, n| sum + n }

# 找出最長字串find the longest wordlongest = ["cat", "sheep", "bear"].inject do |memo, word| ( memo.length > word.length )? memo : wordend

Page 74: Ruby 程式語言綜覽簡介

code block僅執⾏行⼀一次呼叫

file = File.new("testfile", "r")# ...處理檔案

file.close

File.open("testfile", "r") do |file| # ...處理檔案

end# 檔案自動關閉

Page 75: Ruby 程式語言綜覽簡介

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"

Page 76: Ruby 程式語言綜覽簡介

帶參數的 code blockdef 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!"

Page 77: Ruby 程式語言綜覽簡介

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 objectproc_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!"

Page 78: Ruby 程式語言綜覽簡介

傳遞不定參數def my_sum(*val) val.inject(0) { |sum, v| sum + v }end

puts my_sum(1,2,3,4)

# 輸出 10

Page 79: Ruby 程式語言綜覽簡介

參數尾 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

Page 80: Ruby 程式語言綜覽簡介

例外處理raise, begin, rescue, ensure

begin puts 10 / 0rescue => e puts e.classensure # ...end

# 輸出 ZeroDivisionError

raise "Not works!!"# 丟出一個 RuntimeError

# 自行自定例外物件

class MyException < RuntimeError end

raise MyException

Page 81: Ruby 程式語言綜覽簡介

2. Ruby 的特點Ruby supports multiple programming paradigms

Page 82: Ruby 程式語言綜覽簡介

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

Page 83: Ruby 程式語言綜覽簡介

Everything in Ruby is object, even class.

Page 84: Ruby 程式語言綜覽簡介

Ruby Object Model

class Aend

class B < Aend

obj = B.new

obj.class # B B.superclass # AB.class # Class obj B

Object

Class

A

class class

super

super

Page 85: Ruby 程式語言綜覽簡介

class object is an object of the class Class

obj B

Object

Class

A

class class

super

super

class

class

class

class Aend

class B < Aend

obj = B.new

obj.class # B B.superclass # AB.class # Class

Page 86: Ruby 程式語言綜覽簡介

class Aend

module Bend

module Cend

class D < A include B include Cend

D.ancestors=> [D, C, B, A, Object, Kernel, BasicObject]

module

obj D

A

MixinB,C

class

super

super

Page 87: Ruby 程式語言綜覽簡介

class A def foo endend

obj1 = A.newobj2 = A.new

what’s metaclass?

obj2

Object

A

class

super

obj2class

Page 88: Ruby 程式語言綜覽簡介

obj2

Object

A

class

super

obj2’s metaclass

obj2class

super

class A def foo endend

obj1 = A.newobj2 = A.new

def obj2.bar # only obj2 has bar method, # called singleton methodend

# another wayclass << obj1 def baz #only obj1 has baz method endend

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

Page 89: Ruby 程式語言綜覽簡介

AA’s

metaclass

super

Classclass

B

class

class A # way1 def self.foo end # way2 class << self def bar end end end

# way3def A.bazend

A.fooA.barA.baz

class object has its metaclass too. so the singleton method is class

method!!

Page 90: Ruby 程式語言綜覽簡介

動態型別 (duck typing)會聒聒叫的就是鴨⼦子

# 鴨子

class Duck def quack puts "quack!" endend # 野鴨 (不用繼承)class Mallard def quack puts "qwuaacck!! quak!" endend

Page 91: Ruby 程式語言綜覽簡介

Class 不是 Type⼀一個物件可以做什麼才是重點

birds = [Duck.new, Mallard.new, Object.new]

# 迭代陣列,並呼叫方法 (無須擔心型別)

birds.each do |duck| duck.quack if duck.respond_to? :quackend

Page 92: Ruby 程式語言綜覽簡介

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

Page 93: Ruby 程式語言綜覽簡介

prototype-based programmingLike JavaScript, Ruby can do, too

Animal = Object.new

def Animal.runend

def Animal.sitend

Cat = Animal.cloneCat.run

Dog = Animal.cloneDog.run

Page 95: Ruby 程式語言綜覽簡介

“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

Page 96: Ruby 程式語言綜覽簡介

2. Functional Programming函數式程式設計

http://www.slideshare.net/ihower/fp-osdc2012v2

https://github.com/JuanitoFatas/Ruby-Functional-Programming

Page 97: Ruby 程式語言綜覽簡介

(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 endend

highest_price # 900

Page 98: Ruby 程式語言綜覽簡介

Higher-Order Functions(cont.)

tickets = { "a" => 1100, "b" => 900, "c" => 800 }

tickets.map{ |x| x[1] }.select{ |x| x < 1000 }.max # 900

Page 99: Ruby 程式語言綜覽簡介

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 blockFile.open("myfile.txt", 'w') do |f| f.write("Lorem ipsum dolor sit amet") f.write("Lorem ipsum dolor sit amet") end

Page 100: Ruby 程式語言綜覽簡介

Dynamic CallbacksSinatra 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

Page 101: Ruby 程式語言綜覽簡介

Dynamic Callbacksserver = 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 2010server.execute("/goodbye") # goodbye at Wed Apr 21 17:33:42 +0800 2010

Page 102: Ruby 程式語言綜覽簡介

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

Page 103: Ruby 程式語言綜覽簡介

(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

Page 104: Ruby 程式語言綜覽簡介

Everything is an expression (cont.)

message = if found_dog == my_dog name = found_dog.name "We found our dog #{name}!"else "No luck"end

Page 105: Ruby 程式語言綜覽簡介

(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]

Page 106: Ruby 程式語言綜覽簡介

3. Metaprogramming⽤用程式寫程式

http://ihower.tw/blog/archives/4279

Page 107: Ruby 程式語言綜覽簡介

Two types of meta-programming

• Code Generation

• eg. Rails scaffold

• Reflection

• eg. Class Macro

Page 108: Ruby 程式語言綜覽簡介

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

Page 109: Ruby 程式語言綜覽簡介

Introspection (反射機制)

# 這個物件有什麼方法

Object.methods=> ["send", "name", "class_eval", "object_id", "new", "singleton_methods", ...] # 這個物件有這個方法嗎?

Object.respond_to? :name=> true

Page 110: Ruby 程式語言綜覽簡介

define_method動態定義⽅方法

class Dragon define_method(:foo) { puts "bar" }

['a','b','c','d','e','f'].each do |x| define_method(x) { puts x } endend

dragon = Dragon.newdragon.foo # 輸出 "bar"dragon.a # 輸出 "a"dragon.f # 輸出 "f"

Page 111: Ruby 程式語言綜覽簡介

Rails exampleclass Firm < ActiveRecord::Base has_many :clients has_one :account belongs_to :conglomorateend

# has_many 是 AciveRecord 的 class method# 其內容是動態定義出 Firm 的一堆 instance methods

firm = Firm.find(1)firm.clientsfirm.clients.sizefirm.clients.buildfirm.clients.destroy_all

Page 112: Ruby 程式語言綜覽簡介

Memorize example(Class Macro)

class Account

def calculate @calculate ||= begin sleep 10 # expensive calculation 5 end end end

a = Account.newa.caculate # need waiting 10s to get 5a.caculate # 5a.caculate # 5a.caculate # 5

Page 113: Ruby 程式語言綜覽簡介

memoize methodclass Account def calculate sleep 2 # expensive calculation 5 end

memoize :calculate end

a = Account.newa.calculate # need waiting 10s to get 5a.calculate # 5

Page 114: Ruby 程式語言綜覽簡介

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 endend

Page 115: Ruby 程式語言綜覽簡介

It’s general for any classclass Car def run sleep 100 # expensive calculation “done” end

memoize :run end

c = Car.newc.run # need waiting 100s to get donec.run # done

Page 116: Ruby 程式語言綜覽簡介

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

Page 117: Ruby 程式語言綜覽簡介

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 endend

car = Car.new

car.go_to_taipei# go to taipei

car.blah # NoMethodError: undefined method `blah`

Page 118: Ruby 程式語言綜覽簡介

XML builder examplebuilder = 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>

Page 119: Ruby 程式語言綜覽簡介

DSL(Domain-Specific Language)

• Internal DSL

• 沿⽤用程式語⾔言本⾝身的 Syntax

• Ruby 有⾮非常好的能⼒力可以作為 Internal DSL 之⽤用

• External DSL

• ⾃自⾏行發明 Syntax,再⽤用程式語⾔言去解析

Page 120: Ruby 程式語言綜覽簡介

4. Encodings

http://ihower.tw/blog/archives/2722

Page 121: Ruby 程式語言綜覽簡介

UCS v.s. CSI

• UCS (Universal Character Set)

• 語⾔言內部統⼀一轉換成使⽤用 UTF-16 或 UTF-8,Java/Python/Perl 等⼤大部分語⾔言都這樣做

• CSI (Character Set Independent)

• Ruby 內建⽀支援 99 種 Encodings,並不做轉換

Page 122: Ruby 程式語言綜覽簡介

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.

Page 123: Ruby 程式語言綜覽簡介

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"]

Page 124: Ruby 程式語言綜覽簡介

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

Page 125: Ruby 程式語言綜覽簡介

In Ruby 1.9, String has attached Encoding object, and works in

characters.

Page 126: Ruby 程式語言綜覽簡介

Transcoding改變編碼

utf8 = "測試"utf8.bytesize # 6utf8.bytes.to_a # [230, 184, 172, 232, 169, 166]

big5 = utf8.encode("big5")

big5.encoding.name # ”Big5”big5.bytesize # 4big5.bytes.to_a # [180, 250, 184, 213]

Page 127: Ruby 程式語言綜覽簡介

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>'

Page 128: Ruby 程式語言綜覽簡介

Force Transcoding改變編碼,但不改 byte data

utf8 = "測試"

big5 = utf8.encode("big5")big5.valid_encoding?=> true

big5.force_encoding("utf-8")big5.valid_encoding?=> false

Page 129: Ruby 程式語言綜覽簡介

Force Transcoding fails編碼不對無法進⼀一步操作

big5.valid_encoding? # falsebig5 =~ /123456/

=> ArgumentError: invalid byte sequence in UTF-8 from (irb):11 from /usr/local/bin/irb19:12:in `<main>'

Page 130: Ruby 程式語言綜覽簡介

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 + utf8puts my_resume # "My Résumé"puts my_resume.encoding.name # UTF-8

Page 131: Ruby 程式語言綜覽簡介

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>'

Page 132: Ruby 程式語言綜覽簡介

3. Ruby 的實作

Page 133: Ruby 程式語言綜覽簡介

程式語⾔言和程式語⾔言的實作,是兩回事

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

Page 134: Ruby 程式語言綜覽簡介

CRuby / MRI (Matz's Ruby Interpreter)

• 1.8.7 is dead

• 1.9.3

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

Page 135: Ruby 程式語言綜覽簡介

JRuby

Page 136: Ruby 程式語言綜覽簡介

Rubinius

Page 137: Ruby 程式語言綜覽簡介

Concurrency models 的爭論

• process-based

• CRuby has GVL (global VM lock)

• thread-based

• reactor pattern

• eventmachine (Ruby library)

• node.js (JavaScript)

Page 138: Ruby 程式語言綜覽簡介

IronRuby

Page 139: Ruby 程式語言綜覽簡介

MacRuby

Page 140: Ruby 程式語言綜覽簡介

RubyMotion

Page 141: Ruby 程式語言綜覽簡介

mruby

Page 142: Ruby 程式語言綜覽簡介

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

Page 143: Ruby 程式語言綜覽簡介

Web framework

• MVC

• ORM

• URL Routing

• View Template

Page 144: Ruby 程式語言綜覽簡介
Page 145: Ruby 程式語言綜覽簡介
Page 146: Ruby 程式語言綜覽簡介

Web Designer Tools• Sass/Less/Haml

• Compass

• Middleman

Page 147: Ruby 程式語言綜覽簡介
Page 148: Ruby 程式語言綜覽簡介
Page 149: Ruby 程式語言綜覽簡介
Page 150: Ruby 程式語言綜覽簡介

Testing/BDDRuby community loves testing

• RSpec

• Cucumber

http://ihower.tw/blog/archives/5438

http://ihower.tw/blog/archives/5983

Page 151: Ruby 程式語言綜覽簡介

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.

Page 152: Ruby 程式語言綜覽簡介

Terminology changedNew paradigm: Executable Specification

• “Test” becomes “Spec”

• “Assertion” becomes “Expectation”

• “test method” becomes “example” (RSpec)

• “test case” becomes “example group” (RSpec)

Page 153: Ruby 程式語言綜覽簡介
Page 154: Ruby 程式語言綜覽簡介

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 寫法

Page 155: Ruby 程式語言綜覽簡介

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 endend

RSpec 寫法

Page 156: Ruby 程式語言綜覽簡介
Page 157: Ruby 程式語言綜覽簡介

DevOps

• Chef

• Puppet

• Vagrant

Page 158: Ruby 程式語言綜覽簡介
Page 159: Ruby 程式語言綜覽簡介
Page 160: Ruby 程式語言綜覽簡介
Page 161: Ruby 程式語言綜覽簡介

Mac

Page 162: Ruby 程式語言綜覽簡介

Mac

Page 163: Ruby 程式語言綜覽簡介

Blogging(static HTML generator)

Page 164: Ruby 程式語言綜覽簡介

Redmine

Page 165: Ruby 程式語言綜覽簡介

5. Ruby ⽣生態圈

Page 166: Ruby 程式語言綜覽簡介

1. Editors & IDEs

Page 167: Ruby 程式語言綜覽簡介
Page 168: Ruby 程式語言綜覽簡介
Page 169: Ruby 程式語言綜覽簡介

Vim for Rails

Page 170: Ruby 程式語言綜覽簡介

Emacs for Rails

Page 171: Ruby 程式語言綜覽簡介

2. Web Services & Monitors

Page 172: Ruby 程式語言綜覽簡介
Page 173: Ruby 程式語言綜覽簡介
Page 174: Ruby 程式語言綜覽簡介
Page 175: Ruby 程式語言綜覽簡介

3.Hosting

Page 176: Ruby 程式語言綜覽簡介

3.aPaaS (Platform as a Service)

Page 177: Ruby 程式語言綜覽簡介
Page 178: Ruby 程式語言綜覽簡介
Page 179: Ruby 程式語言綜覽簡介

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

Page 180: Ruby 程式語言綜覽簡介
Page 181: Ruby 程式語言綜覽簡介
Page 182: Ruby 程式語言綜覽簡介

3.b IaaS (Infrastructure as a service)

Cloud Hosing

Page 183: Ruby 程式語言綜覽簡介
Page 184: Ruby 程式語言綜覽簡介
Page 185: Ruby 程式語言綜覽簡介

4. Consulting

Page 186: Ruby 程式語言綜覽簡介
Page 187: Ruby 程式語言綜覽簡介
Page 188: Ruby 程式語言綜覽簡介
Page 189: Ruby 程式語言綜覽簡介
Page 190: Ruby 程式語言綜覽簡介
Page 191: Ruby 程式語言綜覽簡介

http://www.workingwithrails.com/

Page 192: Ruby 程式語言綜覽簡介
Page 193: Ruby 程式語言綜覽簡介
Page 194: Ruby 程式語言綜覽簡介

5. Conferences

Page 195: Ruby 程式語言綜覽簡介
Page 196: Ruby 程式語言綜覽簡介
Page 197: Ruby 程式語言綜覽簡介
Page 198: Ruby 程式語言綜覽簡介
Page 199: Ruby 程式語言綜覽簡介
Page 200: Ruby 程式語言綜覽簡介
Page 201: Ruby 程式語言綜覽簡介
Page 202: Ruby 程式語言綜覽簡介
Page 203: Ruby 程式語言綜覽簡介

6. Books

Page 204: Ruby 程式語言綜覽簡介
Page 205: Ruby 程式語言綜覽簡介
Page 206: Ruby 程式語言綜覽簡介

http://www.pragprog.com/

Page 207: Ruby 程式語言綜覽簡介
Page 208: Ruby 程式語言綜覽簡介
Page 209: Ruby 程式語言綜覽簡介
Page 210: Ruby 程式語言綜覽簡介
Page 211: Ruby 程式語言綜覽簡介
Page 212: Ruby 程式語言綜覽簡介
Page 213: Ruby 程式語言綜覽簡介

閱讀練習時,⼩小⼼心 Rails 版本差異1.2, 2.0, 2.1, 2.2, 2.3, 3.0, 3,1, 3.2

4.0 書籍尚未上市

Page 214: Ruby 程式語言綜覽簡介

http://guides.rubyonrails.org/

Page 215: Ruby 程式語言綜覽簡介
Page 216: Ruby 程式語言綜覽簡介
Page 217: Ruby 程式語言綜覽簡介

7. Video

Page 218: Ruby 程式語言綜覽簡介

http://peepcode.com/

Page 219: Ruby 程式語言綜覽簡介
Page 220: Ruby 程式語言綜覽簡介

8. Website & Blog(free)

Page 221: Ruby 程式語言綜覽簡介

http://weblog.rubyonrails.org/

Page 222: Ruby 程式語言綜覽簡介

http://www.rubyinside.com/

Page 223: Ruby 程式語言綜覽簡介

http://ruby5.envylabs.com

Page 224: Ruby 程式語言綜覽簡介

http://railscasts.com/

Page 225: Ruby 程式語言綜覽簡介

http://www.rubyflow.com/

Page 226: Ruby 程式語言綜覽簡介
Page 227: Ruby 程式語言綜覽簡介

http://github.com/

Page 228: Ruby 程式語言綜覽簡介
Page 229: Ruby 程式語言綜覽簡介

9. Ruby Communityin Taiwan

Page 230: Ruby 程式語言綜覽簡介
Page 231: Ruby 程式語言綜覽簡介
Page 232: Ruby 程式語言綜覽簡介
Page 233: Ruby 程式語言綜覽簡介
Page 234: Ruby 程式語言綜覽簡介

Ruby Tuesday 聚會

Page 235: Ruby 程式語言綜覽簡介
Page 236: Ruby 程式語言綜覽簡介
Page 237: Ruby 程式語言綜覽簡介

ptt.cc #Ruby 版

Page 238: Ruby 程式語言綜覽簡介

http://railsfun.tw/

Page 239: Ruby 程式語言綜覽簡介

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/ecosystemhttp://infoether.com/ruby-and-rails-whitepaper

Page 240: Ruby 程式語言綜覽簡介

We’re hiring

• Ruby on Rails developer

• Front-end web developer

• http://faria.co