Skip to content

Instantly share code, notes, and snippets.

@blocknotes
Last active July 5, 2018 18:33
Show Gist options
  • Select an option

  • Save blocknotes/0754008a5e8b55e93fb273885c568b68 to your computer and use it in GitHub Desktop.

Select an option

Save blocknotes/0754008a5e8b55e93fb273885c568b68 to your computer and use it in GitHub Desktop.
Ruby - dry-validation gem examples
require 'dry-validation'
schema = Dry::Validation.Schema do
required(:name).filled
required(:age).maybe(:int?)
optional(:sex).value( included_in?: %w(M F) )
end
hash = { name: 'Jane', email: 'jane@doe.org' }
hash[:age] = 21
hash[:sex] = 'f' # {:sex=>["must be one of: M, F"]}
result = schema.call( hash )
p result.success?
p result.errors
require 'dry-validation'
schema = Dry::Validation.Schema do
required(:address).schema do
required(:city).filled(min_size?: 3)
required(:street).filled
required(:phone_numbers).each(:int?)
required(:country).schema do
required(:name).filled
required(:code).filled
end
end
end
data = { address: { city: 'Vicenza', street: 'via boh', country: { name: 'Italy', code: 'IT' } } }
data[:address][:phone_numbers] = [ 4321, 9999, 6543, nil ]
# {:address=>{:phone_numbers=>{3=>["must be an integer"]}}}
result = schema.call( data )
p result.success?
p result.errors
require 'dry-validation'
schema = Dry::Validation.Schema do
[ :k1, :k2, [ :kk1, :kk2 ] ].each do |key|
if key.is_a? Array
key.each do |sub_key|
required( sub_key ).filled
end
else
required( key ).filled
end
end
end
data = { k2: '...' }
result = schema.call( data )
p result.success?
p result.errors
require 'dry-validation'
VALUE_TYPES = [ Array, BigDecimal, Date, DateTime, Float, Hash, Integer, String, Time ].freeze
fields = {
k1: Integer,
k2: Integer,
sub: {
kk1: String,
kk2: true
}
}
schema = Dry::Validation.Schema do
fields.each do |key, value|
if value.is_a? Hash
required( key ).schema do
value.each do |sub_key, sub_value|
if VALUE_TYPES.include? sub_value
required( sub_key ).value( type?: sub_value )
else
required( sub_key ).filled
end
end
end
elsif VALUE_TYPES.include? value
required( key ).value( type?: value )
else
required( key ).filled
end
end
end
data = { k1: 1, k2: 2, sub: { kk1: '?' } }
data[:sub][:kk2] = 4
result = schema.call( data )
p result.success?
p result.errors
require 'dry-validation'
VALUE_TYPES = [ Array, BigDecimal, Date, DateTime, Float, Hash, Integer, String, Time ].freeze
# Base
class BaseModel
@@schema = Dry::Validation.Schema
def self.schema
@@schema
end
end
# Child
class Model2 < BaseModel
@@schema = Dry::Validation.Schema do
required( :kk1 ).value( :int? )
required( :kk2 ).filled
end
end
fields = {
k1: Integer,
k2: Integer,
sub: Model2
# sub: sub_schema
# sub: {
# kk1: String,
# kk2: true
# }
}
schema = Dry::Validation.Schema do
fields.each do |key, value|
if value.is_a? Hash
required( key ).schema do
value.each do |sub_key, sub_value|
if VALUE_TYPES.include? sub_value
required( sub_key ).value( type?: sub_value )
else
required( sub_key ).filled
end
end
end
elsif VALUE_TYPES.include? value
required( key ).value( type?: value )
elsif value.ancestors.include? BaseModel
required( key ).schema( value.schema )
else
required( key ).filled
end
end
end
data = { k1: 1, k2: 2, sub: { kk1: 3 } }
data[:sub][:kk2] = '4'
result = schema.call( data )
p result.success?
p result.errors
require 'date'
require 'dry-validation'
VALUE_TYPES = [ Array, BigDecimal, Date, DateTime, Float, Hash, Integer, String, Time ].freeze
# Base
class BaseModel
class << self
attr_accessor :fields
def schema
return @schema if defined? @schema
list = fields
@schema = Dry::Validation.Schema do
list.each do |key, value|
if VALUE_TYPES.include? value
required( key ).value( type?: value )
elsif defined? value.schema
required( key ).schema( value.schema )
elsif value.is_a? Hash
required( key ).schema do
value.each do |sub_key, sub_value|
if VALUE_TYPES.include? sub_value
required( sub_key ).value( type?: sub_value )
else
required( sub_key ).filled
end
end
end
else
required( key ).filled
end
end
end
end
end
end
# Child 1
class Model1 < BaseModel
@fields = {
m1_1: String,
m1_2: Integer,
m1_3: true,
mod1_obj: {
m1_s1_1: Date
}
}
end
# Child 2
class Model2 < BaseModel
@fields = {
m2_1: Integer,
mod1: Model1
}
end
###
data = { m2_2: 2, mod1: { m1_1: '3', m1_3: '5' } }
data[:m2_1] = 1
data[:mod1][:m1_2] = 4
data[:mod1][:mod1_obj] = { m1_s1_1: Date.today }
result = Model2.schema.call( data )
p result.success?
p result.errors
require 'date'
require 'dry-validation'
VALUE_TYPES = [ Array, BigDecimal, Date, DateTime, Float, Hash, Integer, String, Time ].freeze
# Base
class BaseModel
class << self
attr_accessor :fields
def schema
return @schema if defined? @schema
list = fields
@schema = Dry::Validation.Schema do
list.each do |key, value|
if VALUE_TYPES.include? value
required( key ).value( type?: value )
elsif defined? value.schema
required( key ).schema( value.schema )
elsif value.is_a? Hash
required( key ).schema do
value.each do |sub_key, sub_value|
if VALUE_TYPES.include? sub_value
required( sub_key ).value( type?: sub_value )
elsif defined? sub_value.schema
required( sub_key ).schema( sub_value.schema )
else
required( sub_key ).filled
end
end
end
elsif value.is_a? Array
unless value.empty?
row = value.first
required( key ).each do
schema do
row.each do |sub_key, sub_value|
if VALUE_TYPES.include? sub_value
required( sub_key ).value( type?: sub_value )
elsif defined? sub_value.schema
required( sub_key ).schema( sub_value.schema )
else
required( sub_key ).filled
end
end
end
end
end
else
required( key ).filled
end
end
end
end
end
end
# Child 1
class Model1 < BaseModel
@fields = {
m1_1: String,
m1_2: Integer,
m1_3: true,
mod1_obj: {
m1_s1_1: Date
}
}
end
# Child 2
class Model2 < BaseModel
@fields = {
m2_1: Integer,
mod1: Model1,
arr: [{
m2a_1: Integer,
m2a_2: String
}]
}
end
###
data = { m2_2: 2, mod1: { m1_1: '3', m1_3: '5' } }
data[:m2_1] = 1
data[:mod1][:m1_2] = 4
data[:mod1][:mod1_obj] = { m1_s1_1: Date.today }
data[:arr] = [ { m2a_1: 4, m2a_2: '4' }, { m2a_2: 'boh', m2a_1: 123 } ]
result = Model2.schema.call( data )
p result.success?
p result.errors
require 'date'
require 'dry-validation'
VALUE_TYPES = [ Array, BigDecimal, Date, DateTime, Float, Hash, Integer, String, Time ].freeze
# Base
class BaseModel
class << self
attr_accessor :fields
def schema
return @schema if defined? @schema
set = proc do |rules, values|
values.each do |key, value|
if VALUE_TYPES.include? value
rules.required( key ).value( type?: value )
elsif defined? value.schema
rules.required( key ).schema( value.schema )
elsif value.is_a?( Hash )
rules.required( key ).schema { set.call self, value }
elsif value.is_a?( Array ) && !value.empty?
rules.required( key ).each do
rules.schema { set.call self, value.first }
end
else
rules.required( key ).filled
end
end
end
list = fields
@schema = Dry::Validation.Schema { set.call self, list }
end
end
end
# Child 1
class Model1 < BaseModel
@fields = {
m1_1: String,
m1_2: Integer,
mod1_obj: {
m1_s1_1: Date
}
}
end
# Child 2
class Model2 < BaseModel
@fields = {
m2_1: Integer,
m2_2: true,
mod1: Model1,
arr: [{
m2a_1: Integer,
m2a_2: String
}]
}
end
###
data = { m2_2: 2, mod1: { m1_1: '3' } }
data[:m2_1] = 1
data[:mod1][:m1_2] = 4
data[:mod1][:mod1_obj] = { m1_s1_1: Date.today }
data[:arr] = 1 # {:arr=>["must be an array"]}
# data[:arr] = [ { m2a_1: 4, m2a_2: '4' }, { m2a_2: 'boh', m2a_1: 123 } ]
result = Model2.schema.call( data )
p result.success?
p result.errors
require 'date'
require 'dry-validation'
VALUE_TYPES = [ Array, BigDecimal, Date, DateTime, Float, Hash, Integer, String, Time ].freeze
# Base
class BaseModel
class << self
attr_accessor :fields
# Prepare the dry validation schema
# @note @fields with the list of fields is required, if type is specified @fields[type] is required
# @param type [Symbol] the schema type
# @return [Dry::Validation.Schema] the dry validation schema
def schema( type = :default )
@schema = {} unless defined? @schema
return @schema[type] if @schema.include? type
set = proc do |rules, values|
values.each do |key, value|
if VALUE_TYPES.include? value
rules.required( key ).value( type?: value )
elsif defined? value.schema
rules.required( key ).schema( value.schema( type ) )
elsif value.is_a?( Hash )
rules.required( key ).schema { set.call self, value }
elsif value.is_a?( Array ) && !value.empty?
rules.required( key ).each do
rules.schema { set.call self, value.first }
end
elsif value.is_a?( FalseClass )
rules.optional( key )
else
rules.required( key ).filled
end
end
end
list = type == :default ? fields : fields[type]
@schema[type] = Dry::Validation.Schema { set.call self, list }
end
end
end
# Child 1
class Model1 < BaseModel
@fields = {
create: {
a_string: String,
an_int: false,
an_obj: {
a_date: Date
}
}
}
end
# Child 2
class Model2 < BaseModel
@fields = {
create: {
another_int: Integer,
another_string: true,
a_model: Model1,
an_array: [{
array_int: Integer,
array_string: String
}]
},
update: {
another_int: Integer,
another_string: String
}
}
end
###
data = { another_string: 2, a_model: { a_string: '3' } }
data[:another_int] = 1
# data[:a_model][:an_int] = 4
data[:a_model][:an_obj] = { a_date: Date.today }
data[:an_array] = [ { array_int: 4, array_string: '4' }, { array_string: 'boh', array_int: 123 } ]
result = Model2.schema( :create ).call( data )
p result.success?
p result.errors
puts "\n"
###
more_data = { another_string: 'str1', another_int: 0 }
result = Model2.schema( :update ).call( more_data )
p result.success?
p result.errors
puts "\n"
###
p Model1.schema( :create ).rules.keys
p Model2.schema( :create ).rules.keys
# p Model1.schema( :update ).rules.keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment