Grape เป็น Ruby framework ยอดนิยมสำหรับสร้าง RESTful APIs Exception handling มีบทบาทสำคัญในการטיחความเสถียรและความน่าเชื่อถือของแอปพลิเคชันใดๆ รวมถึงที่สร้างด้วย Grape
บทความนี้จะสำรวจพื้นฐานของ Grape exception handling รวมถึงการปรับแต่ง exceptions เราจะแตะบาง best practices และวิธี integrate แอปของคุณกับ AppSignal เพื่อ enhanced error monitoring และ management
มาเริ่มกัน!
พื้นฐานของ Grape Exception Handling
ใน tutorial นี้ เราจะเห็นวิธีจัดการ exceptions ใน Grape API ที่สร้างใน Rails ฉันทำ demo job board API สำหรับนี้ และคุณสามารถดู source code บน GitHub
การ Raise Exception
คุณสามารถ raise exception ใน Grape โดยใช้ error! ตัวอย่างเช่น ใน job API ที่กล่าวไว้ข้างต้น เรามี route show ที่คืนค่า job ตาม ID เราสามารถคืนค่า 404 error เมื่อ record ไม่พร้อมใช้งาน ได้แบบนี้:
เมื่อคุณ raise exception คุณจะอยากจัดการมันในวิธีที่ "unique" — คุณน่าจะไม่ส่ง raised exception ไปให้ users
ใน Ruby เรามี default mechanism สำหรับ exception handling มันทำงานโดยการ wrap โค้ดที่อาจ raise exception ใน block begin Block rescue ใช้จัดการ exception ที่ถูก raise
นี่คือลักษณะในสถานการณ์ปกติ:
เมธอด rescue_from
เมื่อคุณ raise exceptions หรือพวกมันเกิดขึ้นโดยไม่มีส่วนเกี่ยวข้องโดยตรงของคุณ คุณจะอยากจัดการมันอย่างเหมาะสม โดย default Grape 提供 rescue_from method นี่ช่วยให้คุณระบุ block ของโค้ดที่ execute เมื่อ defined exceptions ถูก raise
ดังนั้น เพื่อ "rescue" หรือจัดการ 404 error ที่เรา raise ก่อนหน้านี้ หรืออีกอันที่เกิดขึ้นใน jobs resource เราสามารถใช้ rescue_from method เมธอดนี้เพิ่มขึ้นไปเหนือ jobs resource
เรายังสามารถระบุ content type ที่จะใช้ได้:
วิธีจัดการ exception นี้ generic เกินไป — เรา rescue ทุกรูปแบบของ exception และคืนค่า error ด้วย status code 404 นั่น misleading หาก API users คาดหวังได้ 400 status code
เราสามารถระบุ exception ที่เราอยากจัดการแทนได้:
เมื่อเราพบ ActiveRecord::RecordNotFound error เราจะคืนค่า error message พร้อม status code 404 มิฉะนั้น จะคืนค่า error message พร้อม status code 500
สิ่งนี้แสดงว่าเราสามารถปรับปรุงสิ่งที่เรามีอยู่ได้ แตถ้าอยากได้ error handler ที่ rescue จาก ทั้งหมด errors นั้นคือที่ที่ customizing exceptions เข้ามามีบทบาท
การปรับแต่ง Exceptions ใน Grape สำหรับ Ruby
ขึ้นอยู่กับประเภทของ error ที่พบ error handler นี้ควรสามารถคืนค่า error message พร้อม status code ที่ถูกต้อง
ขั้นแรก สร้างไฟล์ชื่อ exceptions_handler แล้วเราจะย้าย current exception handlers ของเราเข้าไปในไฟล์:
โมดูล ExceptionHandler ของเราใช้ ActiveSupport::Concern ทำให้เราเข้าถึงฟังก์ชันได้เช่น included และ class_methods ใน snippet ข้างต้น เรามี error handlers ใน block included ดังนั้นทุกที่ที่โมดูลนี้ถูก include พวกมันจะพร้อมใช้งานตามที่กำหนด
เราสามารถไปข้างหน้าและลบ error handler จากไฟล์ที่เรามีไว้ก่อนหน้านี้ แล้วเราสามารถ include โมดูล ExceptionsHandler ใน API entry file ของเรา — api.rb:
มาสร้าง base error class สำหรับ errors ของเรา คลาสนี้จะรับผิดชอบคืนค่า error response
คลาสรับพารามิเตอร์ keyword สองตัว: message string และ status หากไม่ส่ง เราจะใช้ default
ในเมธอด body เราคืนค่า Rack response โดย default rescue_from handler ต้องคืนค่า Rack::Response object, เรียก error!, หรือ raise exception
เราสามารถไปข้างหน้าและใช้มันใน ExceptionsHandler:
เมื่อเราเรียก endpoint /error เราจะเห็น oops คืนค่าเป็น response ณ จุดนี้ เราสามารถสร้างคลาสสำหรับ NotFound errors
คลาส NotFound รับแค่ message เนื่องจากมันสืบทอดจาก BaseError เราจึงไม่ต้องคืนค่า Rack::Response อีกครั้ง เราสามารถไปข้างหน้าและใช้มันใน ExceptionsHandler แบบนี้:
ตอนนี้ หากเราพยายาม raise error แบบนี้ด้วยตนเอง:
สิ่งนี้จะทำงานได้ดี แตstatus code จะเป็น 500 เพราะมันคืนค่า response ใน BaseError class (ในฐานะที่ BaseError class จัดการ error) เพื่อแก้ไข เราต้องปรับ ExceptionHandler ให้ใช้ NotFound class จัดการ error แทนอย่างชัดเจน
ดังนั้น ทุกครั้งที่เจอ error ที่ตรงกับ ActiveRecord::RecordNotFound และ V1::Exceptions::NotFound ใช้ Exceptions::NotFound มิฉะนั้น ใช้ Exceptions::BaseError
คุณเห็นว่าเราจะต้องการ rescue_from blocks เฉพาะเจาะจงเมื่อเราสร้าง error classes เพิ่มขึ้น เราสามารถปรับปรุงได้โดยใช้ case statements:
Et voilà!
Best Practices และ Tips
แม้จะมี best practices เยอะมากที่คุณสามารถนำมาใช้สำหรับ exception handling นี่คือ quick tips ไม่กี่ข้อที่ควรปฏิบัติ:
- Group related exceptions: ตามที่เห็นในโค้ดข้างต้น การจัดกลุ่ม related exceptions ช่วยให้เรามี maintainable code เมื่อจำนวน exceptions ที่เราอยากจัดการเพิ่มขึ้น เราสามารถเพิ่มพวกมันเข้าไปใน list ได้
- ใช้ helpers เช่น
error!เพื่อ raise exceptions ได้เร็ว นี่ทำให้ exception handling ของคุณง่ายขึ้น - ใช้ exception monitoring tools เช่น AppSignal
AppSignal Integration: Grape สำหรับ Ruby
AppSignal ช่วยให้คุณ monitor และ track errors ในแอปพลิเคชันของคุณ การ integrate AppSignal กับ Grape API ของคุณให้ valuable insights เข้าไปใน exceptions คู่มือนี้แสดงวิธี integrate AppSignal กับ Grape API ของคุณ ทุกครั้งที่ error เกิดขึ้นใน API คุณจะเห็นมันใน AppSignal dashboard ของคุณ แบบนี้:

สรุป
Exception handling เป็นแง่มุมสำคัญของการพัฒนา APIs ที่แข็งแกร่ง ใน tutorial นี้ เราได้เห็นวิธีจัดการ exceptions ใน Grape API อย่างเหมาะสม เรายังได้ชม best practices บางอย่างและ AppSignal integration สำหรับ Grape แบบสั้นๆ
Exception handling เป็นกระบวนการที่ต่อเนื่อง — สิ่งที่คุณต้องปรับปรุงอย่างสม่ำเสมอ
Happy coding!
P.S. หากคุณต้องการอ่านโพสต์ Ruby Magic ทันทีที่เผยแพร่ ให้สมัครสมาชิก newsletter Ruby Magic ของเรา และจะไม่พลาดโพสต์เด็ดๆ ไป!
P.P.S. คุณรู้ไหมว่า AppSignal มี Active Record integration? ค้นพบเพิ่มเติม