Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ข้อยกเว้นการดีบักใน Rails

เมื่อเกิดข้อผิดพลาดในแอปพลิเคชัน 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