Những ngoại lệ phổ biến trong Ruby on Rails
Trong khi làm việc với Ruby, chúng ta rất hay gặp phải các thông báo lỗi về Exception, sau đây là sơ đồ phân cấp các Exception trong Ruby với class Exception là gốc chính: Exception NoMemoryError ScriptError LoadError NotImplementedError SyntaxError SignalException Interrupt ...
Trong khi làm việc với Ruby, chúng ta rất hay gặp phải các thông báo lỗi về Exception, sau đây là sơ đồ phân cấp các Exception trong Ruby với class Exception là gốc chính:
Exception NoMemoryError ScriptError LoadError NotImplementedError SyntaxError SignalException Interrupt StandardError ArgumentError IOError EOFError IndexError LocalJumpError NameError NoMethodError RangeError FloatDomainError RegexpError RuntimeError SecurityError SystemCallError SystemStackError ThreadError TypeError ZeroDivisionError SystemExit
Trong đó ta có thể thấy được rằng StandardError là một superclass với nhiều class con chứa các lỗi phổ biến nhất mà chúng ta thường gặp, sau đây chúng ta sẽ cùng tìm hiểu về các lỗi ấy.
NoMethodError
undefined method `grade' for nil:NilClass undefined method `<<' for {}:Hash
Khi một phương thức được gọi cho 1 đối tượng cụ thể không tồn tại thì lỗi này được trả về, phổ biến nhất là nil:Nilclass
[1] pry(main)> nil.grade NoMethodError: undefined method `grade' for nil:NilClass [2] pry(main)>
Nếu không có yêu cầu đặc biệt cho việc xử lý kết quả (ví dụ như chỉ dùng kết quả để show) thì bạn hãy sử dụng try để tránh lỗi này:
[2] pry(main)> nil.try(:something) => nil [3] pry(main)>
NameError
undefined local variable or method `grade' for # uninitialized constant Report
Lỗi trên xảy ra khi 1 biến không được khởi tạo, cách sửa lỗi này đó là gán giá trị khởi tạo cho nó.
NoMethodError(cho private method)
[6] pry(main)> u.password_complexity NoMethodError: private method `password_complexity' called for #<User:0x00000016063680>
Lỗi này ta có thể gặp khi truy cập trực tiếp một private object method từ một object. Ta có thể tránh việc này bằng cách chuyển method sang public hoặc dùng send:
[7] pry(main)> u.send(:password_complexity) => nil [8] pry(main)>
ActiveRecord::RecordNotFound
[8] pry(main)> User.find 10000 User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 10000 LIMIT 1 ActiveRecord::RecordNotFound: Couldn't find User with 'id'=10000
Lỗi xảy ra khi ra muốn truy xuất một bản ghi có id không tồn tại trong DB bằng find chảng hạn.Để tránh lỗi này chúng ta có thể sử dụng find_by hoặc where:
[2] pry(main)> User.find_by_id(params[:id]) => nil [3] pry(main)> User.find_by(id: params[:id]) => nil [4] pry(main)> User.where(id: params[:id]).first => nil
TypeError
[9] pry(main)> "1" + 2 TypeError: no implicit conversion of Fixnum into String
Khi cộng một String và 1 số Integer thì sẽ phát sinh lỗi này, lỗi này có thể xuất hiện khi ta thực hiện thao tác với nhiều loại khác nhau như String, FixNum, Array, Hash, Float, để tránh lỗi này thì ta nên convert các object về cùng 1 kiểu:
[3] pry(main)> "1" + 2 TypeError: no implicit conversion of Fixnum into String from (pry):3:in `+' [4] pry(main)> "1".to_i + 2 => 3 [5] pry(main)>
ArgumentError
wrong number of arguments (0 for 1)
Lỗi này xảy ra khi ta gọi hàm mà truyền vào số lượng tham số không chính xác như khi định nghĩa hàm, chảng hạn:
my_grade = student(college, grade) def student(college) # Argument error end def student(college, grade = 0) # works fine as grade is assigned 0. end
Truyền đúng số lượng tham số hoặc xét giá trị mặc định cho những tham số có thể không nhất thiết cần truyền khi gọi hàm là cách giải quyết lỗi này.