เมื่อเกิดข้อผิดพลาดในแอปพลิเคชัน Rails ของคุณ ข้อยกเว้นและการติดตามสแต็กจะช่วยคุณค้นหาว่าปัญหาเกิดขึ้นที่ใด หลังจากที่รู้ว่าเกิดอะไรขึ้นที่ไหน เราก็ต้องหา ทำไม มันเกิดขึ้น. ในบทความนี้ เราจะใช้ backtrace เพื่อค้นหาจุดบกพร่องในแอปพลิเคชัน Rails
NoMethodError (undefined method `request_uri' for #<URI::Generic >):
app/models/product.rb:8:in `download_image!'
app/controllers/products_controller.rb:5:in `create'
ในข้อยกเว้นตัวอย่างนี้ เราได้รับ NoMethodError
ด้วย undefined method `request_uri' for #<URI::Generic >
เป็นข้อความของมัน เนื่องจากข้อยกเว้นนี้ไม่ได้บอกเราทันทีว่าปัญหาคืออะไร เราจึงต้องตรวจสอบการติดตามสแต็กเพื่อดูว่าเกิดอะไรขึ้น
app/models/product.rb:8:in `download_image!'
app/controllers/products_controller.rb:5:in `create'
เมื่อดูที่การติดตามสแต็ก เราได้เรียนรู้ว่ามีข้อยกเว้นจาก download_image!
วิธีการใน Product
แบบอย่าง. เราจะดำเนินการตรวจสอบโค้ดต่อไป และดำเนินการตามสแต็กเทรซเพื่อค้นหาว่ามีอะไรผิดปกติ
การเปิดโมเดลแสดงให้เห็นว่าบรรทัดที่ 8 (ซึ่งยกข้อยกเว้นจาก) เรียก Net::HTTP.get(uri)
ดังนั้นดูเหมือนว่า uri
ไม่ใช่วัตถุที่เราคาดหวังให้เป็น
require 'net/http'
class Product < ApplicationRecord
after_save :download_image!
def download_image!
uri = URI(image_url)
contents = Net::HTTP.get(uri)
File.open("public#{local_image_path}", 'wb') do |file|
file.write contents
end
end
def local_image_path
"/product_#{id}.png"
end
end
ตั้งแต่ download_image!
วิธีการคือ after_save
โทรกลับ เรารู้ว่าจะดำเนินการทันทีหลังจากบันทึกผลิตภัณฑ์ใหม่
uri
ตัวแปรถูกสร้างขึ้นจากวิธีการที่ชื่อ image_url
ในบรรทัดที่ 7 หากต้องการทราบว่ามาจากไหน เราจะดูที่ stack trace อีกครั้งเพื่อดู Product#create
เมธอดถูกเรียกจาก ProductsController#create
.
class ProductsController < ApplicationController
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product, notice: 'Product was successfully created.'
else
render :new
end
end
private
def product_params
params.require(:product).permit(:title, :description, :image_url, :price)
end
end
อ้า! ProductsController#create
สร้างผลิตภัณฑ์ใหม่ด้วย product_params
ซึ่งรวมถึง :image_url
พารามิเตอร์ที่เรากำลังมองหา
เรารู้จัก image_url
แอตทริบิวต์ถูกใช้เพื่อสร้าง URI ที่เสียหาย ถ้าเราปล่อย image_url
ฟิลด์ว่างเมื่อสร้างผลิตภัณฑ์ใหม่ เราสามารถทำซ้ำปัญหาได้สำเร็จ
ในกรณีนี้ การสร้าง URI
ด้วยสตริงว่างเป็นค่าผลลัพธ์ใน URI::Generic
วัตถุแทนที่จะเป็น URI::HTTP
เนื่องจากไม่สามารถระบุรูปแบบของ URL ได้ เนื่องจากอันแรกไม่มี #request_uri
เมธอด มันทำให้เกิด NoMethodError
จาก Net::HTTP.get
.
ขึ้นอยู่กับข้อกำหนดของโครงการ การเพิ่มการตรวจสอบเพื่อให้แน่ใจว่าฟิลด์ไม่ว่างเปล่าสามารถแก้ไขปัญหาได้ การตรวจสอบความถูกต้องเพื่อให้แน่ใจว่า URL รูปภาพไม่ว่างเปล่าเท่านั้นจะไม่สามารถแก้ไขปัญหาที่เป็นไปได้ทั้งหมดกับการใช้งานนี้ (เราจะยังคงได้รับข้อยกเว้นเมื่อค่าที่ส่งผ่านไม่ใช่ URL เป็นต้น) แต่เป็นการเริ่มต้นที่ดี
การติดตามข้อยกเว้นโดยใช้การติดตามสแต็ก
บันทึกของ Rails เป็นวิธีที่ดีในการดีบักปัญหา แม้ว่าข้อยกเว้นที่ยกมานั้นไม่สมเหตุสมผลนักเมื่อมองแวบแรก แต่การรื้อถอนขั้นตอนที่โค้ดดำเนินการอย่างระมัดระวังเพื่อแก้ไขปัญหามักจะเป็นวิธีที่ดีในการค้นหาว่าเกิดอะไรขึ้น แม้ว่าแหล่งที่มาของปัญหาจะถูกฝังไว้ ลึกลงไปในแอปของคุณอีกเล็กน้อย
เราชอบที่จะรู้ว่าคุณชอบบทความนี้อย่างไร หากคุณมีคำถามเกี่ยวกับบทความนี้ และต้องการอ่านเกี่ยวกับอะไรต่อไป โปรดแจ้งให้เราทราบที่ @AppSignal