can_has_validations 0.5.1 → 0.6.0
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39feb1ba720229383addaf65d761cf38ce5da9545b5e402cf3a9a064523b987a
|
4
|
+
data.tar.gz: 8128047f635300ddae1771a1d997f22cb732391d79f4d49bc7c2e47bab2c51a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 212be440432bb1ff47193b1948a603138d01e813fd88d0978c8fd8c9ab1d61d39dee23914a1aa0b91abbd955a520b991c609b0a597571e253edfa3242f8006b2
|
7
|
+
data.tar.gz: 190a03e36354954c46b9a1b4e45e22197cad6b6819565320446f55fb9e6f6ed3cbfe42d038afd141ba9ca61f087da392c84464636a7c5ce12bea3035c38b01e7
|
data/README.md
CHANGED
@@ -5,6 +5,7 @@ ActiveModel.
|
|
5
5
|
|
6
6
|
Validations provided:
|
7
7
|
|
8
|
+
* Array
|
8
9
|
* Email
|
9
10
|
* Existence
|
10
11
|
* Grandparent
|
@@ -29,6 +30,35 @@ Add it to your `Gemfile`:
|
|
29
30
|
|
30
31
|
|
31
32
|
|
33
|
+
## Array validator ##
|
34
|
+
|
35
|
+
Many database engines allow for arrays of attributes. This validates each
|
36
|
+
member element of those arrays.
|
37
|
+
|
38
|
+
It is able to use most existing validators that themselves work on individual
|
39
|
+
attribute values (including standard Rails validators, others that are part of
|
40
|
+
this gem, and likely many from other gems too).
|
41
|
+
|
42
|
+
By default, it will stop validation of an array attribute after the first error
|
43
|
+
per validator, regardless of how many elements might fail validation. This both
|
44
|
+
improves performance as well as avoids producing a large number of duplicate
|
45
|
+
error messages. Add `multiple_errors: true` on `:array` or any individual
|
46
|
+
sub-validator to instead return all errors (useful if each error message will
|
47
|
+
vary based on the element's value).
|
48
|
+
|
49
|
+
validates :tags,
|
50
|
+
array: {
|
51
|
+
format: /\A[^aeiou]*\z/,
|
52
|
+
length: 5..10
|
53
|
+
}
|
54
|
+
|
55
|
+
validates :permissions,
|
56
|
+
array: {
|
57
|
+
multiple_errors: true,
|
58
|
+
format: /\A[^aeiou]*\z/
|
59
|
+
}
|
60
|
+
|
61
|
+
|
32
62
|
## Email validator ##
|
33
63
|
|
34
64
|
Ensures an attribute is generally formatted as an email. It uses a basic regex
|
@@ -51,7 +81,7 @@ avoid any potential conflicts).
|
|
51
81
|
Mongoid 3 and 4 also exhibit the same behavior as Rails 4, even under Rails 3,
|
52
82
|
so this is useful with Mongoid as well.
|
53
83
|
|
54
|
-
validates :name,
|
84
|
+
validates :name, existence: true
|
55
85
|
|
56
86
|
|
57
87
|
## Grandparent validator ##
|
data/lib/can_has_validations.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'active_model/validations'
|
2
|
+
|
3
|
+
%w(array email existence grandparent hostname ordering url write_once).each do |validator|
|
2
4
|
require "can_has_validations/validators/#{validator}_validator"
|
3
5
|
end
|
4
6
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# validates each member element of an array attribute
|
2
|
+
#
|
3
|
+
# by default will allow only the first error per validator, regardless of how
|
4
|
+
# many elements might fail validation. this improves performance as well as
|
5
|
+
# averting a large number of repeating error messages.
|
6
|
+
# use multiple_errors: true on :array or a single sub-validator to enable the
|
7
|
+
# full set of errors. this is potentially useful if each error message will
|
8
|
+
# vary based upon the array element's contents.
|
9
|
+
#
|
10
|
+
# usage:
|
11
|
+
# validates :tags,
|
12
|
+
# array: {
|
13
|
+
# format: /\A[^aeiou]*\z/,
|
14
|
+
# length: 5..10
|
15
|
+
# }
|
16
|
+
#
|
17
|
+
# validates :permissions,
|
18
|
+
# array: {
|
19
|
+
# multiple_errors: true,
|
20
|
+
# format: /\A[^aeiou]*\z/
|
21
|
+
# }
|
22
|
+
|
23
|
+
module ActiveModel
|
24
|
+
module Validations
|
25
|
+
class ArrayValidator < ActiveModel::EachValidator
|
26
|
+
attr_reader :validators
|
27
|
+
|
28
|
+
def initialize(options)
|
29
|
+
record_class = options[:class]
|
30
|
+
super
|
31
|
+
record_class.prepend DefaultKeys
|
32
|
+
|
33
|
+
defaults = @options.dup
|
34
|
+
validations = defaults.slice!(*record_class.send(:_validates_default_keys), :attributes)
|
35
|
+
|
36
|
+
raise ArgumentError, "You need to supply at least one array validation" if validations.empty?
|
37
|
+
|
38
|
+
defaults[:attributes] = attributes
|
39
|
+
|
40
|
+
@validators = validations.map do |key, options|
|
41
|
+
next unless options
|
42
|
+
key = "#{key.to_s.camelize}Validator"
|
43
|
+
|
44
|
+
begin
|
45
|
+
klass = key.include?("::".freeze) ? key.constantize : record_class.const_get(key)
|
46
|
+
rescue NameError
|
47
|
+
raise ArgumentError, "Unknown validator: '#{key}'"
|
48
|
+
end
|
49
|
+
|
50
|
+
validator = klass.new(defaults.merge(_parse_validates_options(options)))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_each(record, attribute, array_values)
|
55
|
+
@validators.each do |validator|
|
56
|
+
error_count = count_errors(record)
|
57
|
+
|
58
|
+
Array(array_values).each do |value|
|
59
|
+
validator.validate_each(record, attribute, value)
|
60
|
+
|
61
|
+
# to avoid repeating error messages, stop after a single error
|
62
|
+
unless validator.options[:multiple_errors]
|
63
|
+
break if error_count != count_errors(record)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def count_errors(record)
|
73
|
+
# more efficient than calling record.errors.size
|
74
|
+
record.errors.messages.sum{|key, val| val.blank? ? 0 : val.size }
|
75
|
+
end
|
76
|
+
|
77
|
+
def _parse_validates_options(options)
|
78
|
+
case options
|
79
|
+
when TrueClass
|
80
|
+
{}
|
81
|
+
when Hash
|
82
|
+
options
|
83
|
+
when Range, Array
|
84
|
+
{ in: options }
|
85
|
+
else
|
86
|
+
{ with: options }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
module DefaultKeys
|
92
|
+
private
|
93
|
+
|
94
|
+
# When creating custom validators, it might be useful to be able to specify
|
95
|
+
# additional default keys. This can be done by overwriting this method.
|
96
|
+
def _validates_default_keys
|
97
|
+
super + [:multiple_errors]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: can_has_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thomas morgan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -56,12 +56,12 @@ files:
|
|
56
56
|
- Rakefile
|
57
57
|
- lib/can_has_validations.rb
|
58
58
|
- lib/can_has_validations/locale/en.yml
|
59
|
+
- lib/can_has_validations/validators/array_validator.rb
|
59
60
|
- lib/can_has_validations/validators/email_validator.rb
|
60
61
|
- lib/can_has_validations/validators/existence_validator.rb
|
61
62
|
- lib/can_has_validations/validators/grandparent_validator.rb
|
62
63
|
- lib/can_has_validations/validators/hostname_validator.rb
|
63
64
|
- lib/can_has_validations/validators/ordering_validator.rb
|
64
|
-
- lib/can_has_validations/validators/safe_uniqueness_validator.rb
|
65
65
|
- lib/can_has_validations/validators/url_validator.rb
|
66
66
|
- lib/can_has_validations/validators/write_once_validator.rb
|
67
67
|
- lib/can_has_validations/version.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# better behaved version of the uniqueness validator
|
2
|
-
# Difference is it doesn't puke if the foreign_key is an invalid type (for
|
3
|
-
# example, an invalid string being provided for UUID type key). Instead,
|
4
|
-
# returns an error about being unable to find the key value.
|
5
|
-
# eg: validates :user_id, safe_uniqueness: true
|
6
|
-
|
7
|
-
class SafeUniquenessValidator < ActiveRecord::Validations::UniquenessValidator
|
8
|
-
def validate_each(record, attribute, value)
|
9
|
-
record.transaction(requires_new: true) do
|
10
|
-
super
|
11
|
-
end
|
12
|
-
rescue ActiveRecord::StatementInvalid
|
13
|
-
record.errors.add(attribute, "%{attribute} %{value} not found", options.except(:case_sensitive, :scope).merge(value: value))
|
14
|
-
end
|
15
|
-
end
|