sukima 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b0f853475790323284d4fe5b10a7cacf89dc188d8475cbc8b71362f9a91f29b9
4
+ data.tar.gz: 9e02cc197ee1e5c2a544c9523d2d07cf4f8c7e0ff33864853a13acfd8d486e90
5
+ SHA512:
6
+ metadata.gz: ca640d8347b57db0df371ae7138167930f9368cedbff5669f6e05e180f07a1a84f478d4e1d76c123aa41718b5ed92a6ae7fd9777968185a07c50a7d904f5350c
7
+ data.tar.gz: b561b6fbfde7f97c07af05c918596f61fcb148f5ed569a7e6304a64753ad850d1a770d0b570e2cb7e9637d19bcaccf082a43235334f5fefcb2d47414f9510fad
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sukima
4
+ class Constraints
5
+ @registrations = {}
6
+
7
+ class << self
8
+ attr_reader :registrations
9
+
10
+ def const_added(const_name)
11
+ constrant_name = const_name.to_s
12
+ constrant_name.gsub!(/(?<=[[:lower:]])(?=[[:upper:]])/, '_')
13
+ constrant_name.downcase!
14
+ @registrations[constrant_name.to_sym] = const_get(const_name).new
15
+ end
16
+ end
17
+
18
+ class Type
19
+ def call(type, value)
20
+ "should be #{type}" unless value.nil? || value.is_a?(type)
21
+ end
22
+ end
23
+
24
+ class In
25
+ def call(range, value)
26
+ "should be in #{range}" unless range.include?(value)
27
+ end
28
+ end
29
+
30
+ class Format
31
+ def call(pattern, value)
32
+ "should match #{pattern.source}" unless value.is_a?(String) && pattern.match?(value)
33
+ end
34
+ end
35
+
36
+ class Length
37
+ def call(args, value)
38
+ case args
39
+ when Integer
40
+ "should have length of #{args}" unless value.respond_to?(:length) && value.length == args
41
+ when Range
42
+ "should have length in #{args}" unless value.respond_to?(:length) && args.include?(value.length)
43
+ end
44
+ end
45
+ end
46
+
47
+ class Nonnil
48
+ def call(_, value)
49
+ 'should not be nil' if value.nil?
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/sukima/dsl.rb ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sukima
4
+ class Dsl
5
+ def initialize(value, error_field)
6
+ @value = value
7
+ @error_field = error_field
8
+ end
9
+
10
+ def field(name, *args, **, &)
11
+ schema = args.first.is_a?(Sukima) ? args.shift : Sukima.new(*args, **, &)
12
+ if @value.key?(name)
13
+ result = schema.validate(@value[name])
14
+ @error_field[name] = result unless result.valid?
15
+ elsif schema.constraints[:required]
16
+ @error_field[name] = ErrorField.new(errors: ['is required'])
17
+ end
18
+ end
19
+
20
+ def items(*args, **, &)
21
+ schema = args.first.is_a?(Sukima) ? args.shift : Sukima.new(*args, **, &)
22
+ @value.each_with_index do |item, index|
23
+ result = schema.validate(item)
24
+ @error_field[index] = result unless result.valid?
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sukima
4
+ class ErrorField
5
+ attr_accessor :errors
6
+
7
+ def initialize(errors: [])
8
+ @children = {}
9
+ @errors = errors
10
+ end
11
+
12
+ def [](name)
13
+ @children[name]
14
+ end
15
+
16
+ def []=(name, value)
17
+ @children[name] = value
18
+ end
19
+
20
+ def dig(*)
21
+ @children.dig(*)
22
+ end
23
+
24
+ def valid?
25
+ return false if @errors.any?
26
+
27
+ @children.each_value { return false unless _1.valid? }
28
+ true
29
+ end
30
+
31
+ def messages(path = [])
32
+ prefix = path.empty? ? '' : "#{path.join('.')} "
33
+ result = @errors.dup.map! { "#{prefix}#{_1}" }
34
+ @children.map do |name, error_field|
35
+ result.concat(error_field.messages([*path, name]))
36
+ end
37
+ result
38
+ end
39
+
40
+ def to_h
41
+ { errors: @errors, children: @children.transform_values(&:to_h) }
42
+ end
43
+
44
+ protected
45
+
46
+ attr_reader :children
47
+ end
48
+ end
data/lib/sukima.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sukima/constraints'
4
+ require 'sukima/dsl'
5
+ require 'sukima/error_field'
6
+
7
+ class Sukima
8
+ attr_reader :constraints, :block
9
+
10
+ def initialize(**constraints, &block)
11
+ @constraints = constraints
12
+ @block = block
13
+ end
14
+
15
+ def validate(value)
16
+ error_field = ErrorField.new
17
+ @constraints.each do |key, args|
18
+ next if key == :required
19
+
20
+ message = Constraints.registrations[key].call(args, value)
21
+ error_field.errors << message if message
22
+ end
23
+ Dsl.new(value, error_field).instance_exec(value, &@block) if @block
24
+ error_field
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sukima
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Weihang Jian
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-06-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.24'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.24'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.64'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.64'
69
+ description: Sukima is a lightweight data validation library for Ruby written in only
70
+ 100+ lines of code. It provides a simple and flexible way to define constraints
71
+ for data and validate it.
72
+ email: tonytonyjan@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - lib/sukima.rb
78
+ - lib/sukima/constraints.rb
79
+ - lib/sukima/dsl.rb
80
+ - lib/sukima/error_field.rb
81
+ homepage: https://github.com/tonytonyjan/sukima
82
+ licenses:
83
+ - MIT
84
+ metadata:
85
+ rubygems_mfa_required: 'true'
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.3'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.5.9
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Lightweight data validation library for Ruby.
105
+ test_files: []