Last active
July 5, 2018 18:33
-
-
Save blocknotes/0754008a5e8b55e93fb273885c568b68 to your computer and use it in GitHub Desktop.
Ruby - dry-validation gem examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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