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: c8eada0f5dd41202696bbab1b493bb017489452ed29459b3f48925236eaec01d
4
- data.tar.gz: 357ffbc02deb80c773b0b0f604c8dc0f773d7fd62da030f7fa03299a0fe3ba20
3
+ metadata.gz: 39feb1ba720229383addaf65d761cf38ce5da9545b5e402cf3a9a064523b987a
4
+ data.tar.gz: 8128047f635300ddae1771a1d997f22cb732391d79f4d49bc7c2e47bab2c51a4
5
5
  SHA512:
6
- metadata.gz: d5a8f3386d4e3d420a4492370a77479658557f0d5d97e3f04fc7fe95bb04934a9e23cc4146b6f2be60d20db25a049b8387bc46ee1f6dd6156b175b69a8f598e1
7
- data.tar.gz: 6cfa0fab71ff63d23c0d53c9b3780107b99a0af9a126cc695022613fe6b6b5ff28f68315706cd1153114d2c3e90bfb65401d9e4c99ba6fde8578c02c9982c82c
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, presence: true
84
+ validates :name, existence: true
55
85
 
56
86
 
57
87
  ## Grandparent validator ##
@@ -1,4 +1,6 @@
1
- %w(email existence grandparent hostname ordering url write_once).each do |validator|
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
@@ -1,3 +1,3 @@
1
1
  module CanHasValidations
2
- VERSION = '0.5.1'
2
+ VERSION = '0.6.0'
3
3
  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.5.1
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-05-18 00:00:00.000000000 Z
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