hashy_validator 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb2d96afac20d3a5de238c5909ba7001ebfabdbbb790ea9b0ead248853018005
4
- data.tar.gz: 299cb764bb7dfcd2bc69ef07cd791d8b76726b69eb0f7a12a0f28c7b1d71d55f
3
+ metadata.gz: 65bbe593f0a313de084f7bd4a7ab23075422a068a7bea5dc6903f55a7243b09e
4
+ data.tar.gz: b86b243a6e39958a38b8c51bd1d2ce2644e0581a6929956faf74d8c83cab2a34
5
5
  SHA512:
6
- metadata.gz: 6d27b7aa8aae40311a1526fd5fd70c38f962e646d5a73618295f24b874e29cca0d76661111dfbeb7fccf86ccbc5e199201ac0ef4dea5293d0e8838ea2615f401
7
- data.tar.gz: 6a2c04d418e28ad116b0d70b2b6d31c58bd0ffff4aa9aaf9e1f3648f8cacbcc4556a90894bb835a7da4b6430d20b42a1e84a9b4a51e64345e2cf4f0b971f76af
6
+ metadata.gz: af7fd7055e2bf2462ae5784668f7c42d502abfd293e72c4ded6d17d5694182b92342ffb3f22a45063534d81ad53b15c0652092e66490abe46a8428a8acfba166
7
+ data.tar.gz: 74a8d08f9409cd379a2be4af5a82118323ed36dbfb097cddac2fc9b8860348efb37d401c18da6040dbd04bc70adde05483dd72d600fc716d1c58af1d5c7fbd2b
data/CHANGELOG.md CHANGED
@@ -5,9 +5,26 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ### [0.1.3](https://www.github.com/flecto-io/hashy-validator/compare/v0.1.2...v0.1.3) (2024-01-13)
8
+ ### [0.1.5](https://www.github.com/flecto-io/hashy-validator/compare/v0.1.4...v0.1.5) (2024-09-05)
9
9
 
10
10
 
11
+ ### Bug Fixes
12
+
13
+ * add hashy_object ([35e1ccf](https://www.github.com/flecto-io/hashy-validator/commit/35e1ccf1cff9d95df069961c8ac1b3fec6d23645))
14
+
15
+ ### [0.1.4](https://www.github.com/flecto-io/hashy-validator/compare/v0.1.3...v0.1.4) (2024-08-24)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * Accepts dependencies version of activerecord lower than 8 ([eab4692](https://www.github.com/flecto-io/hashy-validator/commit/eab46925196ada0db0c408037cdf90b9ce4dacca))
21
+
22
+ ### [0.1.2](https://www.github.com/flecto-io/hashy-validator/compare/v0.1.2...v0.1.3) (2024-01-13)
23
+
24
+ ### Changes
25
+
26
+ * Production ready
27
+
11
28
  ### Bug Fixes
12
29
 
13
30
  * changelog ([6b8c151](https://www.github.com/flecto-io/hashy-validator/commit/6b8c15105bd085dafa6358f27f780ad4826a42e7))
data/README.md CHANGED
@@ -8,7 +8,6 @@
8
8
  HashyValidator is a custom Ruby on Rails validator designed to validate an array of hashes based on [HashValidator](https://github.com/jamesbrooks/hash_validator) criteria but also the following new criteria:
9
9
  - `unique`: A value within each hash that has to be unique across the whole array
10
10
 
11
-
12
11
  ## Installation
13
12
 
14
13
  Add this line to your application's Gemfile:
@@ -17,8 +16,6 @@ Add this line to your application's Gemfile:
17
16
  gem 'hashy_validator'
18
17
  ```
19
18
 
20
- <b>THIS GEM IS NOT READY FOR PRODUCTION YET!</b>
21
-
22
19
  And then execute:
23
20
 
24
21
  ```bash
@@ -42,14 +39,20 @@ To leverage HashyValidator in your Rails model, follow these steps:
42
39
  ```ruby
43
40
  class YourModel < ApplicationRecord
44
41
  validates :pricing, hashy_array: {
45
- minutes: HashValidator.multiple('required', 'integer', 'unique'),
46
- price_cents: HashValidator.multiple('required', 'integer')
42
+ minutes: HashValidator.multiple('integer', 'unique'),
43
+ price_cents: HashValidator.multiple('integer')
47
44
  }
48
45
  end
49
46
  ```
50
47
 
51
48
  Customize each entry validators according to [HashValidator](https://github.com/jamesbrooks/hash_validator) criteria
52
49
 
50
+ # Testing
51
+
52
+ ```bash
53
+ rake test
54
+ ```
55
+
53
56
  ## Contributing
54
57
 
55
58
  Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration. To ease up contribution we provide a VSCode _devcontainer_ to run the project in a container.
@@ -14,12 +14,15 @@ Gem::Specification.new do |spec|
14
14
  spec.require_paths = ["lib"]
15
15
  spec.files = Dir["{lib}/**/*"] + ["README.md", "CHANGELOG.md", "hashy_validator.gemspec"]
16
16
 
17
- spec.add_dependency "activerecord", ">= 6.0.0", "<= 7.2.0"
17
+ spec.add_dependency "activerecord", ">= 6.0.0", "< 8.0.0"
18
18
  spec.add_dependency "hash_validator", "~> 1.1"
19
19
 
20
20
  spec.add_development_dependency 'sqlite3', '~> 1.4'
21
21
  spec.add_development_dependency 'rake', '~> 13.1.0'
22
22
  spec.add_development_dependency 'simplecov', '0.17.1'
23
+ spec.add_development_dependency 'rubocop', '~> 1.59'
24
+ spec.add_development_dependency 'rubocop-shopify', '~> 2.14'
25
+ spec.add_development_dependency 'pry', '~> 0.14.1'
23
26
 
24
27
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3")
25
28
  spec.add_development_dependency 'minitest', '>= 5.15.0', '< 5.16'
@@ -1,63 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class HashyArrayValidator < ActiveModel::EachValidator
2
4
  def validate_each(record, attribute, value)
3
- instance_value = HashyValueValidator.new(value)
4
- unless instance_value.is_valid
5
+ instance_value = HashyValueValidator.new(value, options)
6
+
7
+ unless instance_value.valid?
5
8
  record.errors.add(attribute, instance_value.reason)
6
9
  return false
7
10
  end
8
11
 
9
- value = instance_value.value
12
+ unless instance_value.value.is_a?(Array)
13
+ record.errors.add(attribute, :not_an_array)
14
+ return false
15
+ end
10
16
 
11
- # look for boolean and unique validator entries
12
- unique_attrs = {}
13
- boolean_attrs = []
14
- validations =
15
- # force validator keys to be strings
16
- options.stringify_keys.map do |val_attr,val|
17
- if (val.is_a?(HashValidator::Validations::Multiple) && val.validations.include?('boolean')) || (val.is_a?(String) && val == 'boolean')
18
- boolean_attrs << val_attr
19
- [val_attr, val]
20
- elsif val.is_a?(HashValidator::Validations::Multiple) && val.validations.include?('unique')
21
- # if unique key present, then remove that entry (since its not from HashValidator standard) and keep its history
22
- unique_attrs[val_attr] ||= []
23
- # we have to make a new object to remove the unique entry,
24
- # because deleting it directly from the original object (val) would result into deleting the verification forever
25
- new_val = HashValidator::Validations::Multiple.new(val.validations.reject{|v| v == 'unique'})
26
- # return the value
27
- val.validations.blank? ? nil : [val_attr, new_val]
28
- elsif val.is_a?(String) && val == 'unique'
29
- # same as above but substring
30
- unique_attrs[val_attr] ||= []
31
- nil
32
- else
33
- [val_attr, val]
34
- end
35
- end.compact.to_h
17
+ value = instance_value.value
36
18
 
37
19
  # force all array entries to have string keys
38
20
  # discard keys that do not have validators
39
- value = value.map{ |e| e.stringify_keys.slice(*validations.keys) }
21
+ value = value.map { |e| e.stringify_keys.slice(*instance_value.validations.keys) }
40
22
 
41
23
  # we validate each object in the array
42
24
  value.each do |t|
43
25
  # if boolean found as any of the validations we force value to boolean - if present
44
- boolean_attrs.each do |boolean_attr|
45
- t[boolean_attr] = get_boolean_value(t[boolean_attr]) if t.key?(boolean_attr)
26
+ instance_value.boolean_attrs.each do |boolean_attr|
27
+ t[boolean_attr] = HashyValueValidator.get_boolean_value(t[boolean_attr]) if t.key?(boolean_attr)
46
28
  end
47
29
 
48
30
  # keep track of unique values and add error if needed
49
- unique_attrs.keys.each do |unique_attr|
50
- if unique_attrs[unique_attr].include?(t[unique_attr])
31
+ instance_value.unique_attrs.each_key do |unique_attr|
32
+ if instance_value.unique_attrs[unique_attr].include?(t[unique_attr])
51
33
  record.errors.add(attribute, "'#{unique_attr}' not unique")
52
34
  else
53
- unique_attrs[unique_attr] << t[unique_attr]
35
+ instance_value.unique_attrs[unique_attr] << t[unique_attr]
54
36
  end
55
37
  end
56
38
 
57
39
  # use default hash validator
58
- validator = HashValidator.validate(t, validations)
40
+ validator = HashValidator.validate(t, instance_value.validations)
59
41
  unless validator.valid?
60
- validator.errors.each { |k,v| record.errors.add(attribute, "'#{k.to_s}' #{v}") }
42
+ validator.errors.each { |k, v| record.errors.add(attribute, "'#{k}' #{v}") }
61
43
  end
62
44
  end
63
45
 
@@ -65,12 +47,4 @@ class HashyArrayValidator < ActiveModel::EachValidator
65
47
  # we use send write param so we also support attr_accessor attributes
66
48
  record.send("#{attribute}=", value)
67
49
  end
68
-
69
- private
70
-
71
- def get_boolean_value(value)
72
- return true if value == true || value == 'true'
73
- return false if value == false || value == 'false'
74
- nil
75
- end
76
50
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HashyObjectValidator < ActiveModel::EachValidator
4
+ def validate_each(record, attribute, value)
5
+ instance_value = HashyValueValidator.new(value, options)
6
+
7
+ # Do not validate empty hash
8
+ return if instance_value.value.keys.empty?
9
+
10
+ unless instance_value.valid?
11
+ record.errors.add(attribute, instance_value.reason)
12
+ return false
13
+ end
14
+
15
+ if instance_value.value.is_a?(Array)
16
+ record.errors.add(attribute, :not_an_object)
17
+ return false
18
+ end
19
+
20
+ # force all array entries to have string keys
21
+ # discard keys that do not have validators
22
+ value = instance_value.value.stringify_keys.slice(*instance_value.validations.keys)
23
+
24
+ # we validate each object in the array
25
+ # if boolean found as any of the validations we force value to boolean - if present
26
+ instance_value.boolean_attrs.each do |boolean_attr|
27
+ value[boolean_attr] = HashyValueValidator.get_boolean_value(t[boolean_attr]) if value.key?(boolean_attr)
28
+ end
29
+
30
+ # keep track of unique values and add error if needed
31
+ instance_value.unique_attrs.each_key do |unique_attr|
32
+ if instance_value.unique_attrs[unique_attr].include?(value[unique_attr])
33
+ record.errors.add(attribute, "'#{unique_attr}' not unique")
34
+ else
35
+ instance_value.unique_attrs[unique_attr] << t[unique_attr]
36
+ end
37
+ end
38
+
39
+ # use default hash validator
40
+ validator = HashValidator.validate(value, instance_value.validations)
41
+ unless validator.valid?
42
+ validator.errors.each { |k, v| record.errors.add(attribute, "'#{k}' #{v}") }
43
+ end
44
+
45
+ # update the value even if errors found
46
+ # we use send write param so we also support attr_accessor attributes
47
+ record.send("#{attribute}=", value)
48
+ end
49
+ end
@@ -1,42 +1,72 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class HashyValueValidator
2
- def initialize(value)
3
- @value = value.blank? ? [] : value
4
- @valid = true
5
- @reason = nil
6
-
7
- check_parse_value
8
- check_is_array
9
-
10
- @value
11
- end
12
-
13
- def is_valid
14
- @valid
15
- end
16
-
17
- def value
18
- @value
19
- end
20
-
21
- def reason
22
- @reason
23
- end
24
-
25
- private
26
-
27
- def check_parse_value
28
- begin
29
- @value = JSON.parse(@value) if @value.is_a?(String)
30
- rescue JSON::ParserError
31
- @valid = false
32
- @reason = :invalid
33
- end
34
- end
35
-
36
- def check_is_array
37
- unless @value.is_a?(Array)
38
- @valid = false
39
- @reason = :not_an_array
40
- end
41
- end
42
- end
4
+ def initialize(value, options = {})
5
+ @value = value.blank? ? [] : value
6
+ @valid = true
7
+ @reason = nil
8
+ @validations = {}
9
+ @unique_attrs = {}
10
+ @boolean_attrs = []
11
+
12
+ check_parse_value
13
+ define_validations(options)
14
+ end
15
+
16
+ def valid?
17
+ @valid
18
+ end
19
+
20
+ attr_reader :value, :reason, :validations, :unique_attrs, :boolean_attrs
21
+
22
+ def self.get_boolean_value(value)
23
+ return true if [true, "true"].include?(value)
24
+ return false if [false, "false"].include?(value)
25
+
26
+ nil
27
+ end
28
+
29
+ private
30
+
31
+ def check_parse_value
32
+ @value = JSON.parse(@value) if @value.is_a?(String)
33
+ rescue JSON::ParserError
34
+ @valid = false
35
+ @reason = :invalid
36
+ end
37
+
38
+ def define_validations(options)
39
+ # look for boolean and unique validator entries
40
+ unique_attrs = {}
41
+ boolean_attrs = []
42
+ validations =
43
+ # force validator keys to be strings
44
+ options.stringify_keys.map do |val_attr, val|
45
+ is_multiple = val.is_a?(HashValidator::Validations::Multiple)
46
+ if (is_multiple && val.validations.include?("boolean")) || (val.is_a?(String) && val == "boolean")
47
+ boolean_attrs << val_attr
48
+ [val_attr, val]
49
+ elsif is_multiple && val.validations.include?("unique")
50
+ # if unique key present, then remove that entry
51
+ # (since its not from HashValidator standard) and keep its history
52
+ unique_attrs[val_attr] ||= []
53
+ # we have to make a new object to remove the unique entry,
54
+ # because deleting it directly from the original object
55
+ # (val) would result into deleting the verification forever
56
+ new_val = HashValidator::Validations::Multiple.new(val.validations.reject { |v| v == "unique" })
57
+ # return the value
58
+ val.validations.blank? ? nil : [val_attr, new_val]
59
+ elsif val.is_a?(String) && val == "unique"
60
+ # same as above but substring
61
+ unique_attrs[val_attr] ||= []
62
+ nil
63
+ else
64
+ [val_attr, val]
65
+ end
66
+ end.compact.to_h
67
+
68
+ @validations = validations
69
+ @unique_attrs = unique_attrs
70
+ @boolean_attrs = boolean_attrs
71
+ end
72
+ end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HashyValidator
4
- module Version
5
- MAJOR = 0
6
- MINOR = 1
7
- PATCH = 2
8
- STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
9
- end
10
- end
4
+ module Version
5
+ MAJOR = 0
6
+ MINOR = 1
7
+ PATCH = 5
8
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
9
+ end
10
+ end
@@ -1,4 +1,7 @@
1
- require 'active_record'
2
- require 'hash_validator'
3
- require_relative './hashy_validator/hashy_value_validator'
4
- require_relative './hashy_validator/hashy_array_validator'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "hash_validator"
5
+ require_relative "hashy_validator/hashy_value_validator"
6
+ require_relative "hashy_validator/hashy_array_validator"
7
+ require_relative "hashy_validator/hashy_object_validator"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashy_validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Flecto Team
@@ -17,9 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 6.0.0
20
- - - "<="
20
+ - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 7.2.0
22
+ version: 8.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +27,9 @@ dependencies:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  version: 6.0.0
30
- - - "<="
30
+ - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 7.2.0
32
+ version: 8.0.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: hash_validator
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +86,48 @@ dependencies:
86
86
  - - '='
87
87
  - !ruby/object:Gem::Version
88
88
  version: 0.17.1
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.59'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.59'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rubocop-shopify
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.14'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '2.14'
117
+ - !ruby/object:Gem::Dependency
118
+ name: pry
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 0.14.1
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 0.14.1
89
131
  - !ruby/object:Gem::Dependency
90
132
  name: minitest
91
133
  requirement: !ruby/object:Gem::Requirement
@@ -114,6 +156,7 @@ files:
114
156
  - hashy_validator.gemspec
115
157
  - lib/hashy_validator.rb
116
158
  - lib/hashy_validator/hashy_array_validator.rb
159
+ - lib/hashy_validator/hashy_object_validator.rb
117
160
  - lib/hashy_validator/hashy_value_validator.rb
118
161
  - lib/hashy_validator/version.rb
119
162
  homepage:
@@ -134,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
177
  - !ruby/object:Gem::Version
135
178
  version: '0'
136
179
  requirements: []
137
- rubygems_version: 3.3.26
180
+ rubygems_version: 3.4.19
138
181
  signing_key:
139
182
  specification_version: 4
140
183
  summary: Custom Active Model validator for validating arrays of hashes