hashy_validator 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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