can_has_validations 0.5.1 → 0.6.0
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:
|
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
|