0

Active Record Validation in Rails Part II

Phần trước tôi đã giới thiệu về Active Record Validations và một số accs helper Rails cung cấp hỗ trợ chúng ta trong việc xác thực tính đúng đắn của dữ liệu. Trong phần này tôi sẽ giới thiệu những option thường sử dụng khi thao tác với Active Record Validations ^^

Những option validation thường dùng

  • :allow_nil

Tùy chỉnh :allow_nil cho phép sẽ bỏ qua xác thực khi giá trị bị kiểm tra là nil.

class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),

message: "%{value} is not a valid size" }, allow_nil: true
end
  • :allow_blank

Tùy chỉnh :allow_blank này cho phép bỏ qua xác thực khi giá trị thuộc tính là blank?

class Topic < ApplicationRecord
validates :title, length: { is: 5 }, allow_blank: true
end
#console
Topic.create(title: "").valid? # => true
Topic.create(title: nil).valid? # => true
  • :message

Tùy chỉnh :message cho phép ta tùy chỉnh thông báo được thêm vào errors khi xác thực thất bại. Khi tùy chọn này không được sử dụng, Active Record sẽ sử dụng thông báo mặc định cho mỗi helper xác thực. Tùy chọn :message chấp nhận cả String và Proc. String :message có thể bao gồm cả %{value}, %{attribute}, %{model}, những thứ này sẽ được tự động thay thế khi validation lỗi. Sự thay thế này có tương tác với gem I18n. Proc :message sẽ phải truyền vào 2 tham số: object được xác thực và hash với cặp key-value của :model, :attribute và :value.

class Person < ApplicationRecord
# Hard-coded message
validates :name, presence: { message: "must be given please" }
# Message with dynamic attribute value. %{value} will be
replaced with
# the actual value of the attribute. %{attribute} and %{model}
also
# available.

validates :age, numericality: { message: "%{value} seems
wrong" }
# Proc
validates :username,
uniqueness: {
# object = person object being validated
# data = { model: "Person", attribute: "Username", value:
<username> }
message: ->(object, data) do
"Hey #{object.name}!, #{data[:value]} is taken already!
Try again #{Time.zone.tomorrow}"
end
}
end
  • :on

Tùy chọn :on cho phép ta thiết lập khi nào thì xác thực nên xảy ra. Mặc định xác thực sẽ được thực thi trước khi save (cả khi tạo bảng ghi mới lẫn khi update bản ghi). Nếu muốn thay đổi nó, ta có thể sử dụng on: :create để chạy xác thực chỉ khi bản ghi được tạo hoặc on: :update chỉ chạy khi bản ghi được update.

class Person < ApplicationRecord
# it will be possible to update email with a duplicated value
validates :email, uniqueness: true, on: :create
# it will be possible to create the record with a
non-numerical age
validates :age, numericality: true, on: :update
# the default (validates on both create and update)
validates :name, presence: true
end

Ta cũng có thể sử dụng on: để định nghĩa một ngữ cảnh. Ngữ cảnh đó sẽ được kích hoạt bằng cách truyền tên của ngữ cảnh vào valid?, invalid? hoặc save.

class Person < ApplicationRecord
validates :email, uniqueness: true, on: :account_setup
validates :age, numericality: true, on: :account_setup
end
person = Person.new(age: 'thirty-three')
person.valid? # => true
person.valid?(:account_setup) # => false
person.errors.messages
# => {:email=>["has already been taken"], :age=>["is not a
number"]}

person.valid?(:account_setup) sẽ chạy xác thực nhưng sẽ không lưu vào CSDL. person.save(context: :account_setup) xác thực person trong ngưx cảnh account_setup trước khi lưu. Khi ngữ cảnh được kích hoạt, xác thực sẽ chạy cho ngữ cảnh đó và những xác thực (mà không ràng buộc ngữ cảnh) cũng sẽ được thực thi.

class Person < ApplicationRecord
validates :email, uniqueness: true, on: :account_setup
validates :age, numericality: true, on: :account_setup
validates :name, presence: true
end
person = Person.new
person.valid?(:account_setup) # => false
person.errors.messages
# => {:email=>["has already been taken"], :age=>["is not a
number"], :name=>["can't be blank"]}

Tùy chỉnh validation errors

Bên cạnh phương thức valid? và invalid?, Rails cung cấp một số phương thức để làm việc với errors và kiểm tra tính hợp lệ của đối tượng.

  • errors

Hàm này trả về một thể hiện của lớp ActiveModel::Errors chứa tất cả các lỗi dưới dạng Hash. Mỗi key là tên thuộc tính, value là một dãy string chứa tất cả các lỗi của thuộc tính đó.

class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
person = Person.new
person.valid? # => false
person.errors.messages
# => {:name=>["can't be blank", "is too short (minimum is 3
characters)"]}
person = Person.new(name: "John Doe")
person.valid? # => true
person.errors.messages # => {}
  • errors[]

errors[] được sử dụng khi ta muốn kiểm tra thông báo lỗi cho thuộc tính nào đó. Nó sẽ trả về một dãy các string với tất cả các thông báo lỗi cho thuộc tính được đưa vào, mỗi string sẽ là một thông báo lỗi. Nếu không có lỗi nào liên quan tới thuộc tính này, nó sẽ trả về một dãy rỗng.

class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
person = Person.new(name: "John Doe")
person.valid? # => true
person.errors[:name] # => []
person = Person.new(name: "JD")
person.valid? # => false
person.errors[:name] # => ["is too short (minimum is 3
characters)"]
person = Person.new
person.valid? # => false
person.errors[:name]
# => ["can't be blank", "is too short (minimum is 3
characters)"
  • errors.add

Phương thức add cho phép ta thêm một thông báo lỗi liên quan tới thuộc tính cụ thể. Tham số của nó là thuộc tính và thông báo lỗi. Phương thức errors.full_messages (tương đương với errors.to_a) trả về một thông báo lỗi thân thiện hơn với người dùng.

class Person < ApplicationRecord
def a_method_used_for_validation_purposes
errors.add(:name, "cannot contain the characters
!@#%*()_-+=")
end
end
person = Person.create(name: "!@#")
person.errors[:name]
# => ["cannot contain the characters !@#%*()_-+="]

person.errors.full_messages
# => ["Name cannot contain the characters !@#%*()_-+="]
  • errors.details

Ta có thể thiết lập kiểu thông báo lỗi trả về bằng cách sử dụng phương thức errors.add

class Person < ApplicationRecord
def a_method_used_for_validation_purposes
errors.add(:name, :invalid_characters)
end
end
person = Person.create(name: "!@#")
person.errors.details[:name]
# => [{error: :invalid_characters}]

Để tăng tính cụ thể của lỗi, ta có thể thêm các kí tự không được phép có vào trong thể hiện, ta thêm key này vào errors.add

class Person < ApplicationRecord
def a_method_used_for_validation_purposes
errors.add(:name, :invalid_characters, not_allowed:
"!@#%*()_-+=")
end
end
person = Person.create(name: "!@#")
person.errors.details[:name]
# => [{error: :invalid_characters, not_allowed: "!@#%*()_-+="}]

Kết luận

Qua phần 2 này các bạn đã có thể thấy được tầm quan trọng của Active Record Validations trong việc hỗ trợ chúng ta thao tác, xử lý với dữ liệu. Tận dụng và phát huy những điểm mạnh mà Active Record Validations mang lại sẽ giúp hệ thống của các bạn hoàn thiện và chuyên nghiệp hơn rất nhiều.

Cảm ơn các bạn đã đọc hết bài viết, bài viết còn nhiều thiếu sót nên mọi người có thể góp ý cho mình những phần chưa ổn tại phần bình luận nhé ^^ Hẹn gặp lại!

Nguốn tham khảo

Active Record Validations : https://guides.rubyonrails.org/active_record_validations.html


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí