Tìm hiểu Dry Validation trong Ruby On Rails - P1
Bài đăng này đã không được cập nhật trong 5 năm
 Trước tiên, mình sẽ giới thiệu qua về Dry Validation
Trước tiên, mình sẽ giới thiệu qua về Dry Validation
- dry-validationlà thư viện validation data được cung cấp bởi DSL, nó hoat động với bất kỳ dữ liệu đầu vào nào, cho dù nó là một hash, array hay một đối tượng chứa những liệu được lồng sâu vào với nhau.
- Validations được thể hiện thông qua các Contract object. MộtContractsẽ xác dịnh mộtschemavới các kiểu check dữ liệu cơ bản và bất kỳrulesnào có thể áp dụng.rulestrongContractchỉ được áp dụng một khi các giá trị mà chúng dựa vào đã được pass qua các kiểu check dữ liệu cơ bản củaschema.
- Sử dụng nó sẽ nhanh hơn nhiều so với việc chúng ta sử dụng  ActiveRecord/ActiveModel::Validations,strong-parameters.
- Để cho thể sử dụng nó trong project của mình ta cần cài đặt nó trước bằng việc add gem 'dry-validation'vào gemfile của project ROR chúng ta nhé
 Ta bắt đầu tìm hiểu những thứ căn bản của thư viện này nhé:
Ta bắt đầu tìm hiểu những thứ căn bản của thư viện này nhé:
1. Type Validate Basic
- Một số kiểu check validate thường sử dụng trong dry mình có thể kể đến:
- required: buộc trong dữ liệu đầu vào của ta phải có nó
- filled: phải điền dữ liệu cho key, attribute,... (ví dụ: {email: "test@example.com"})
- optional: nó sẽ ko yêu cầu dữ liệu đầu vào phải có, 
    thường sẽ kết hợp với filled để validate dữ liệu
- value: kiểu dữ liệu (string, integer,...) cho key, attribute,...của dữ liệu đầu vào
2. Schemas
- Có thể nói Schemaslà một phần quan trọng củadry-validation, nó sẽ xử lý dữ liệu trước khi nó bị validate bởirules( cònruleslà gì thì bên dưới mình sẽ tìm hiểu rõ hơn nhé ) vàSchemascó thể cung cấp các thông báo lỗi một cách chi tiết nhất
- rulesở đây có thể hiểu là mình sẽ validate các dữ liệu một cách cụ thể hơn (các dữ liệu cần validate một cách logic hơn) mà các type validate của gem không hỗ trợ.
 Định nghĩa một Schema cơ bản
Định nghĩa một Schema cơ bản
- Để định nghĩa một schema chúng ta sẽ sử dụng schemamethod:
class ExampleContract < Dry::Validation::Contract
  schema do
    required(:email).value(:string)
    required(:age).value(:integer)
  end
end
- Ở bên trên ta đã khởi tạo một Contact với việc sử dụng required có nghĩa là đầu vào buộc phải có email,agevà value củaemailphải làstringvà value củaagephải làinteger
- Bây giờ, ta sẽ thử áp dụng Contract chúng ta vừa tạo nhé:
example = ExampleContract.new
result = example.call(age: 21)
# => #<Dry::Validation::Result{:age=>21} errors={:email=>["is missing"]}>
result.to_h
# => {:age=>21}
result.errors.to_h
# => {:email=>["is missing"]}
 Định nghĩa một Schema với Params required
Định nghĩa một Schema với Params required
- Để định nghĩa một schema cho việc validate HTTP parameters, ta sẽ sử dụngparamsmethod:
class ExampleContract < Dry::Validation::Contract
  params do
    required(:email).value(:string)
    required(:age).value(:integer)
  end
end
result = ExampleContract.call('email' => 'namdang@test.com', 'age' => '18')
# => #<Dry::Validation::Result{:email=>"namdang@test.com", :age=>21} errors={}>
result.to_h
# => {:email=>"jane@doe.org", :age=>21}
- Sự khác biệt chính giữa paramsvàschemađơn giản làparamssẽ thực hiện các bắt buộc dành riêng choparamstrước khi áp dụngrules. Trong phầnrulesta sẽ tìm hiểu rõ ràng hơn.
 Định nghĩa một Schema với JSON required
Định nghĩa một Schema với JSON required
- Ta có thể sử dụng jsonđể định nghĩa mộtschemaphù hợp cho việc xác thực JSON data:
class ExampleContract < Dry::Validation::Contract
  json do
    required(:email).value(:string)
    required(:age).value(:integer)
  end
end
result = ExampleContract.call('email' => 'namdang@test.com', 'age' => '18')
# => #<Dry::Validation::Result{:email=>"namdang@test.com", :age=>"21"} errors={:age=>["must be an integer"]}>
result = ExampleContract.call('email' => 'jane@doe.org', 'age' => 18)
# => #<Dry::Validation::Result{:email=>"jane@doe.org", :age=>18} errors={}>
result.to_h
# => {:email=>"namdang@test.com", :age=>18}
 Sử dụng lại schema từ schema khác
Sử dụng lại schema từ schema khác
- Ta có thể sử dụng lại một schemahiện có hoặc multipleschemabằng cách passing nó sangschemachúng ta định nghĩa. Ví dụ:
CategorySchema = Dry::Schema.Params do
 required(:category_id).value(:integer)
 required(:type).value(:string)
end
UserSchema = Dry::Schema.Params do
 required(:user_id).value(:integer) 
end
class PostContract < Dry::Validation::Contract
 params(CategorySchema, UserSchema) do
   required(:name).value(:string)
   required(:content).value(:string) 
 end
end
post = PostContract.new
post.(name: "New Post", content: 1, user_id: 2)
=> #<Dry::Validation::Result{:name=>"New Post", :content=>1, :user_id=>2} 
    # errors={:category_id=>["is missing"], :type=>["is missing"], :content=>["must be a string"]}> 
 Custom Types cho Schema
Custom Types cho Schema
- Khi chúng ta định nghĩa schema sử dụng paramhayjson, ta có thể xử lý cho giá trị dữ liệu đầu vào theo cách ta muốn ví dụ như:
module Types
  include Dry::Types()
  StripString = Types::String.constructor(&:strip)
end
class EmailContract < Dry::Validation::Contract
params do
  required(:email).value(Types::StripString)
end
end
email = EmailContract.new
email.call(email: '   test@test.com   ')
# => #<Dry::Validation::Result{:email=>"test@test.com"} errors={}>
Cảm ơn các bạn đã đọc bài viết của mình
Tài liệu tham khảo: Dry Validation
All rights reserved
 
  
 