Computer >> Máy Tính >  >> Lập trình >> Ruby

Gỡ lỗi ngoại lệ trong Rails

Khi một lỗi xảy ra trong ứng dụng Rails của bạn, ngoại lệ và dấu vết ngăn xếp sẽ giúp bạn tìm nơi xảy ra sự cố. Sau khi biết điều gì đã xảy ra ở đâu, chúng ta cần tìm hiểu tại sao nó đã xảy ra. Trong bài viết này, chúng ta sẽ xem xét việc sử dụng backtrace để tìm ra lỗi trong ứng dụng 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'

Trong trường hợp ngoại lệ ví dụ này, chúng tôi nhận được NoMethodError với undefined method `request_uri' for #<URI::Generic > như thông điệp của nó. Vì ngoại lệ này không cho chúng tôi biết vấn đề là gì ngay lập tức, chúng tôi sẽ cần kiểm tra dấu vết ngăn xếp để tìm hiểu điều gì đã xảy ra.

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

Nhìn vào dấu vết ngăn xếp, chúng tôi biết rằng ngoại lệ đã được tạo ra từ download_image! trên Product người mẫu. Chúng tôi sẽ tiếp tục điều tra về mã và chúng tôi sẽ làm việc theo cách của chúng tôi để tìm ra dấu vết ngăn xếp để tìm ra điều gì đang xảy ra.

Mở mô hình cho thấy dòng 8 (nơi đặt ngoại lệ từ) gọi Net::HTTP.get(uri) , vì vậy nó giống như vậy uri không phải là đối tượng mà chúng tôi mong đợi.

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

Kể từ download_image! phương thức là một after_save gọi lại, chúng tôi biết nó được thực thi ngay sau khi lưu Sản phẩm mới.

uri biến được tạo từ một phương thức có tên image_url trên dòng 7. Để tìm hiểu nguồn gốc của nó, chúng ta sẽ xem xét lại dấu vết ngăn xếp để xem Product#create phương thức được 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 một sản phẩm mới với product_params , bao gồm :image_url tham số chúng tôi đang tìm kiếm.

Chúng tôi biết image_url thuộc tính được sử dụng để xây dựng URI bị hỏng. Nếu chúng ta để image_url trường trống khi tạo sản phẩm mới, chúng tôi có thể tái tạo thành công sự cố.

Trong trường hợp này, tạo URI với một chuỗi trống vì giá trị của nó dẫn đến URI::Generic đối tượng thay vì URI::HTTP , bởi vì nó không thể xác định định dạng của URL. Vì cái trước không có #request_uri , nó tạo ra một NoMethodError từ Net::HTTP.get .

Tùy thuộc vào yêu cầu của dự án, việc thêm xác thực để đảm bảo trường không trống có thể khắc phục sự cố. Chỉ xác thực để đảm bảo rằng URL hình ảnh không trống sẽ không khắc phục được tất cả các vấn đề có thể xảy ra với việc triển khai này (ví dụ:chúng tôi sẽ vẫn nhận được một ngoại lệ khi giá trị được truyền không phải là một URL), nhưng đó là một khởi đầu tốt.

Theo dõi các trường hợp ngoại lệ bằng cách sử dụng dấu vết ngăn xếp

Nhật ký của Rails cung cấp một cách tuyệt vời để gỡ lỗi các vấn đề. Mặc dù ngay từ cái nhìn đầu tiên, các ngoại lệ nêu ra không phải lúc nào cũng có ý nghĩa, nhưng cẩn thận rút lại các bước mã đã thực hiện để giải quyết vấn đề thường là một cách tuyệt vời để tìm ra vấn đề đã xảy ra, ngay cả khi nguồn gốc của vấn đề đã bị chôn vùi. sâu hơn một chút trong ứng dụng của bạn.

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