Daily Archives: 10/11/2016

Rails – Kiểm tra dữ liệu gửi lên form

Trong bài này chúng ta sẽ tìm hiểu cách kiểm tra sự đúng đắn của dữ liệu.

Kiểm tra dữ liệu ở đây là kiểm tra xem dữ liệu được gửi lên có đúng với yêu cầu hay không, cũng có thể xem đây là câu lệnh catch trong quá trình kiểm tra lỗi exception vậy, chẳng hạn như chúng ta yêu cầu người dùng nhập vào email nhưng người dùng nhập sai cấu trúc, hay upload ảnh avatar mà lại gửi lên một file PDF, nguy hiểm hơn nữa là up file ảnh giả – tức file có đuôi .jpg, .png… nhưng lại không chứa dữ liệu ảnh mà chứa mã độc… vì thế chúng ta nên kiểm tra dữ liệu được gửi lên trước khi lưu chúng vào CSDL.

Validator

Trong ứng dụng depot mà chúng ta vừa làm trong các bài trước, chúng ta có tạo một model có tên Product, khi tạo model thì Rails sẽ tạo một lớp cũng có tên Product trong một file là product.rb, và đặt file này trong thư mục app/models, mặc định thì Rails không định nghĩa gì trong lớp này cả:

class Product < ActiveRecord::Base
end

Lớp Product được kế thừa từ lớp ActiveRecord::Base của Rails, trong lớp ActiveRecord::Base có một phương thức tên là validates dùng để kiểm tra dữ liệu. Ví dụ chúng ta sửa lại đoạn code trên như sau:

class Product < ActiveRecord::Base
    validates :title, :description, :image_url, :presence => true
end

Phương thức validates nhận vào danh sách các thuộc tính do chúng ta định nghĩa và các phương thức kiểm tra dữ liệu, ở đây title, descriptionimage_url là các thuộc tính do chúng ta định nghĩa, presence là một phương thức kiểm tra dữ liệu, ý nghĩa của phương thức validates này là kiểm tra xem các thuộc tính có khớp với điều kiện trong phương thức kiểm tra hay không. Ở đây presence nhận vào tham số true tức là bắt buộc các thuộc tính kia không được để trống.

Bạn có thể thử chạy server, tạo một product mới và không điền gì vào 3 trường title, description, image_url thì server sẽ thông báo lỗi:

capture

Chúng ta thử kiểm tra một điều kiện khác như sau:

class Product < ActiveRecord::Base
    validates :title, :description, :image_url, :presence => true
    validates :price, :numericality => {:greater_than_or_equal_to => 1.0}
end

Ở đây phương thức numericality nhận vào giá trị là một đối tượng khác, đối tượng này là greater_than_or_equal_to có giá trị 1.0, ý nghĩa là giá trị phải là số và lớn hơn 1.0.

capture

Một phương thức kiểm tra khác là uniqueness, ví dụ:

class Product < ActiveRecord::Base
    validates :title, :description, :image_url, :presence => true
    validates :price, :numericality => {:greater_than_or_equal_to => 1.0}
    validates :title, :uniqueness => true
end

Ý nghĩa của phương thức này là thuộc tính phải là duy nhất, tức là không có 2 đối tượng/bản ghi nào có thuộc tính này giống nhau.

capture

Ví dụ tiếp theo là phương thức format:

class Product < ActiveRecord::Base
    validates :title, :description, :image_url, :presence => true
    validates :price, :numericality => {:greater_than_or_equal_to => 1.0}
    validates :title, :uniqueness => true
    validates :image_url, :format => {
        :with => %r{\.(gif|jpg|png)\Z}i,
        :message => 'Chi nhan file GIF, JPG, PNG'
    }
end

Phương thức format này nhận vào tham số with có giá trị là một chuỗi Regex (Regular Expression – Biểu thức chính quy), chuỗi này sẽ so sánh chuỗi giá trị với một mẫu nào đó, ở đây mẫu Regex của chúng ta có nghĩa là đường dẫn file ảnh phải kết thúc bằng .jpg, .png hoặc .gif. Ngoài ra chúng ta có thể sửa lại thuộc tính message, thuộc tính này sẽ in thông báo lỗi ra theo ý chúng ta muốn, thuộc tính này không bắt buộc phải có.

capture

Ngoài ra còn có rất nhiều phương thức kiểm tra khác mà mình không đề cập ở đây, bạn có thể tham khảo tại:

http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html

Bạn cũng có thể tự viết phương thức kiểm tra riêng cho mình, nhưng mình sẽ đề cập ở bài khác.