Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Thành Thạo Debug Exception Rails: Dùng Backtrace Để Xác Định Bug

Khi lỗi xảy ra trong Rails app, exception và stack trace giúp tìm nơi vấn đề xảy ra. Sau khi biết gì xảy ra ở đâu, ta cần tìm tại sao nó xảy ra. Bài này đi qua dùng backtrace tìm bug trong Rails application.

NoMethodError (undefined method `request_uri' for #<URI::Generic >): app/models/product.rb:8:in `download_image!' app/controllers/products_controller.rb:5:in `create' 

Trong exception ví dụ, ta nhận NoMethodError với message undefined method `request_uri' for #<URI::Generic >. Vì exception không ngay lập tức nói vấn đề gì, ta inspect stack trace tìm ra chuyện gì xảy ra.

app/models/product.rb:8:in `download_image!' app/controllers/products_controller.rb:5:in `create' 

Nhìn stack trace, ta biết exception raise từ method download_image! trên model Product. Ta tiếp tục điều tra trong code, đi xuống stack trace tìm ra gì sai.

Mở model thấy line 8 (nơi exception raise) gọi Net::HTTP.get(uri), nên uri không phải object ta kỳ vọng.

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

Vì download_image! là after_save callback, ta biết nó execute ngay sau save Product mới.

Biến uri build từ method image_url line 7. Để tìm nó từ đâu, ta nhìn lại stack trace thấy Product#create gọi từ 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

Aha! ProductsController#create tạo product mới với product_params, bao gồm parameter :image_url ta tìm.

Ta biết attribute image_url dùng build broken URI. Nếu để trống field image_url khi tạo product mới, ta reproduce thành công vấn đề.

Trong trường hợp này, tạo URI với empty string làm value kết quả URI::Generic object thay vì URI::HTTP, vì không xác định được format URL. Vì前者没有#request_uri method, nó raise NoMethodError từ Net::HTTP.get.

Tùy yêu cầu project, thêm validation đảm bảo field không empty có thể fix issue. Chỉ validate image URL không empty không fix tất cả vấn đề implementation này (vẫn exception khi value không phải URL), nhưng khởi đầu tốt.

Truy Vết Exception Bằng Stack Trace

Log Rails cung cấp cách tuyệt vời debug issue. Mặc dù raised exception không luôn có ý nghĩa ngay lập tức, carefully retract steps code thực hiện đến issue thường là cách tuyệt vời tìm ra gì sai, ngay khi source problem chui sâu hơn trong app.

Chúng tôi rất muốn biết bạn thấy bài này như thế nào, nếu có câu hỏi, và bạn muốn đọc gì tiếp theo, hãy cho biết @AppSignal.