ไม่มีอะไรเรียบง่ายและน่าเบื่อกว่า case statement มันมาจาก C ใช้แทน if หลายๆ ตัว จบเรื่อง หรือไม่?
จริงๆ case statements ใน Ruby ริชและซับซ้อนกว่าที่คิด มาดูตัวอย่าง:
case "Hi there"
when String
puts "case statements match class"
end
# outputs: "case statements match class"
ตัวอย่างนี้แสดงว่า case statements ไม่ได้ match แค่ ค่า แต่ match คลาส ด้วย เพราะภายใต้ Ruby ใช้ operator === (three equals operator)
ทัวร์เร็วกับ operator ===
เวลาเขียน x === y ใน Ruby คุณกำลังถามว่า "y อยู่ในกลุ่มที่ x แทนไหม?" นี่คำพูดทั่วไป รายละเอียดขึ้นอยู่กับประเภทของกลุ่ม
# เรียก Class.===(item) คืน true ถ้า item เป็น instance ของคลาส
String === "hello" # true
String === 1 # false
Strings, regular expressions และ ranges กำหนด ===(item) เอง พฤติกรรมคาดเดาได้ คุณเพิ่ม triple equals method ให้คลาสของตัวเองได้ด้วย
ตอนนี้เรารู้แล้ว เราทำเคล็ดลับกับ case ได้หลายอย่าง
Match ranges ใน case statements
ใช้ ranges ได้เพราะ range === n คืนค่า range.include?(n) อยู่ใน docs
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
# outputs "case statements match inclusion in a range"
Match regular expressions กับ case statements
ใช้ regex ได้เพราะ /regexp/ === "string" คืน true ก็ต่อเมื่อ string match regex ดู docs ของ Regexp
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
# outputs "they can match regular expressions!"
Match procs และ lambdas
นี่แปลกหน่อย Proc#===(item) เทียบเท่า Proc#call(item) ดู docs ได้ หมายความว่าใช้ lambdas/procs ใน case statement เป็น dynamic matchers ได้
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
# outputs "lambdas"
เขียน Matcher Classes เอง
เพิ่ม custom case behavior ให้คลาสของคุณง่ายแค่กำหนด === เอง ใช้ได้กับการแยก conditional logic ซับซ้อนเป็นคลาสเล็กๆ หลายตัว ตัวอย่าง:
class Success
def self.===(item)
item.status >= 200 && item.status < 300
end
end
class Empty
def self.===(item)
item.response_size == 0
end
end
case http_response
when Empty
puts "response was empty"
when Success
puts "response was a success"
end