better_validations 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +15 -0
- data/lib/better_validations.rb +85 -0
- data/lib/better_validations/errors.rb +59 -0
- data/lib/better_validations/list.rb +24 -0
- data/lib/better_validations/nested_validator.rb +48 -0
- data/lib/better_validations/object.rb +28 -0
- data/lib/better_validations/railtie.rb +4 -0
- data/lib/better_validations/validator.rb +114 -0
- data/lib/better_validations/validators_list.rb +84 -0
- data/lib/better_validations/version.rb +3 -0
- metadata +74 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 451f27d06fabf944c809fe98c5942634ebb0578c054a70b82dcbcd831cafc25f
|
4
|
+
data.tar.gz: 661475b942ccf70af3ae9660fd812c335b4d1b5ee37bf43b05b761505cd5be1c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 270e518392f9702d5640b608b1138d4a8899f4f0fa3cf17a1f1dd22c593a869888dbcc1c405b12113e803d509a81a64b61f6749ee62430c55c49c694e1b9ce0c
|
7
|
+
data.tar.gz: 8e198d598f009d01e7ed7b1d33f5e243753b626d94822a4d5d889162d23046a7ad934a381b5347fdee0cdaea0a7d4f865429818e2c08dfef422c31ff9ed38a8b
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2020 Petr Bazov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# README
|
2
|
+
|
3
|
+
## Development
|
4
|
+
|
5
|
+
1. Clone project.
|
6
|
+
|
7
|
+
2. Copy `.env.example` file to `.env` file.
|
8
|
+
|
9
|
+
3. Feel `.env` file by actual values of DATABASE_USER and DATABASE_PASSWORD.
|
10
|
+
|
11
|
+
4. Run `rails db:create`.
|
12
|
+
|
13
|
+
5. Run `rails s`.
|
14
|
+
|
15
|
+
6. Open `http://localhost:3000/` in browser.
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'better_validations/railtie'
|
2
|
+
|
3
|
+
require_relative 'better_validations/errors'
|
4
|
+
require_relative 'better_validations/object'
|
5
|
+
require_relative 'better_validations/list'
|
6
|
+
require_relative 'better_validations/nested_validator'
|
7
|
+
require_relative 'better_validations/validator'
|
8
|
+
require_relative 'better_validations/validators_list'
|
9
|
+
|
10
|
+
# 1. A module provides a way to get error messages from an active record
|
11
|
+
# keeping structure of nested objects represented by relations
|
12
|
+
# such as belongs_to, has_one, has_many instead of a flat structure. Just call:
|
13
|
+
#
|
14
|
+
# active_record.errors.detailed_messages
|
15
|
+
#
|
16
|
+
# This calling returns a hash such as:
|
17
|
+
#
|
18
|
+
# { field_one: ['Error 1', 'Error 2'],
|
19
|
+
# field_two: ['Error'],
|
20
|
+
# nested_object: { field: ['Error'] },
|
21
|
+
# nested_list: [{ field: ['Error'] }] }
|
22
|
+
#
|
23
|
+
# A "detailed_messages" method has a "wrap_attributes_to" parameter.
|
24
|
+
# You can use it to wrap all attributes except relations by passed key:
|
25
|
+
#
|
26
|
+
# active_record.errors.detailed_messages(wrap_attributes_to: :fields)
|
27
|
+
# { fields: { field_one: ['Error'], field_two: ['Error'] },
|
28
|
+
# nested_object: { fields: { field: ['Error'] } } }
|
29
|
+
#
|
30
|
+
# This module also provides other features.
|
31
|
+
#
|
32
|
+
# 2. Ability to validate nested objects in separated validators with
|
33
|
+
# included ActiveModel::Validations.
|
34
|
+
#
|
35
|
+
# Just include BetterValidations::Validator instead of ActiveModel::Validations
|
36
|
+
# and you will can to validate nested objects with the other validator by
|
37
|
+
# calling a "validate_nested" method:
|
38
|
+
#
|
39
|
+
# class UserValidator
|
40
|
+
# include BetterValidations::Validator
|
41
|
+
#
|
42
|
+
# attr_accessor :email, :password, :personal_info
|
43
|
+
#
|
44
|
+
# validates_presence_of :email, :password
|
45
|
+
# validate_nested :personal_info, PersonalInfoValidator
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# class PersonalInfoValidator
|
49
|
+
# include BetterValidations::Validator
|
50
|
+
#
|
51
|
+
# attr_accessor :first_name, :last_name
|
52
|
+
# validates_presence_of :first_name, :last_name
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# After that you can validate active record object, hash or
|
56
|
+
# ActionController::Parameters by passing them to the validator.
|
57
|
+
# Keys "#{field}" and "#{field}_attributes" are synonyms and fills
|
58
|
+
# a "#{field}=" attr_accessor:
|
59
|
+
#
|
60
|
+
# user = User.new(email: '', personal_info_attributes: { first_name: '' })
|
61
|
+
# user = User.new(personal_info: PersonalInfo.new(last_name: ''))
|
62
|
+
# user = { email: '', personal_info_attributes: { last_name: '' } }
|
63
|
+
# user = { email: '', personal_info: { last_name: '' } }
|
64
|
+
# user = ActionController::Parameters.new(email: '')
|
65
|
+
#
|
66
|
+
# validator = UserValidator.new(user)
|
67
|
+
# validator.valid?
|
68
|
+
# validator.errors.detailed_messages
|
69
|
+
#
|
70
|
+
# 3. Ability to merge validators in order to get merged detailed errors.
|
71
|
+
# Useful when you needs to get errors from multiple validators
|
72
|
+
# or if a part of validations implemented inside a model. Usage:
|
73
|
+
#
|
74
|
+
# validator = validator_one.merge(validator_two, validator_three, object)
|
75
|
+
# validator.valid?
|
76
|
+
# validator.errors.detailed_messages
|
77
|
+
#
|
78
|
+
module BetterValidations
|
79
|
+
# Your code goes here...
|
80
|
+
end
|
81
|
+
|
82
|
+
ActiveModel::Errors.include BetterValidations::Errors
|
83
|
+
ActiveRecord::Base.include BetterValidations::Object
|
84
|
+
ActiveRecord::Associations::CollectionProxy.include BetterValidations::List
|
85
|
+
Array.include BetterValidations::List
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module BetterValidations::Errors
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
included do
|
4
|
+
# Returns the same hash as a 'messages' method
|
5
|
+
# but if an error is happened with a nested object
|
6
|
+
# it will be stored in a nested hash under the key without a dot symbol
|
7
|
+
# instead of an array under the key with dot symbol.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# object.errors.messages == {
|
11
|
+
# field_one: ["can't be blank"],
|
12
|
+
# "nested_object.field_one": ["can't be blank"],
|
13
|
+
# "nested_object.field_two": ["can't be blank"]
|
14
|
+
# }
|
15
|
+
# object.errors.detailed_messages == {
|
16
|
+
# field_one: ["can't be blank"],
|
17
|
+
# nested_object: {
|
18
|
+
# field_one: ["can't be blank"],
|
19
|
+
# field_two: ["can't be blank"]
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
def detailed_messages(wrap_attributes_to: nil)
|
23
|
+
return @messages if @messages.blank?
|
24
|
+
|
25
|
+
# Split errors to field errors and nested objects errors.
|
26
|
+
# A dot symbol means that the error is happened with a nested object.
|
27
|
+
nested_messages, field_messages = @messages.partition do |field, _|
|
28
|
+
base_field_name = field.to_s.split('.').first.to_sym
|
29
|
+
@base.class.reflect_on_association(base_field_name)
|
30
|
+
end.map(&:to_h)
|
31
|
+
|
32
|
+
if wrap_attributes_to.present? && field_messages.present?
|
33
|
+
field_messages = { wrap_attributes_to => field_messages }
|
34
|
+
end
|
35
|
+
|
36
|
+
detailed_messages = field_messages
|
37
|
+
return detailed_messages if nested_messages.blank?
|
38
|
+
|
39
|
+
# Parse nested messages to structure with nested objects and merge.
|
40
|
+
detailed_messages.merge(
|
41
|
+
parse_nested_messages(nested_messages, wrap_attributes_to)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Converts nested messages to detailed structure with nested objects
|
46
|
+
def parse_nested_messages(nested_messages, wrap_attributes_to)
|
47
|
+
# Get names of all relations with errors
|
48
|
+
relations = nested_messages.keys
|
49
|
+
.map { |field| field.to_s.split('.').first }
|
50
|
+
.uniq
|
51
|
+
|
52
|
+
# Collect messages from nested objects
|
53
|
+
relations.map do |relation|
|
54
|
+
object = @base.relation_for_nested_messages(relation)
|
55
|
+
[relation.to_sym, object.detailed_errors_messages(wrap_attributes_to)]
|
56
|
+
end.to_h
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BetterValidations::List
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
included do
|
4
|
+
# A helper method to get messages from the active record collection
|
5
|
+
def detailed_errors_messages(wrap_attributes_to)
|
6
|
+
select { |object| object.errors.messages.present? }.map do |object|
|
7
|
+
messages = object.detailed_errors_messages(wrap_attributes_to)
|
8
|
+
|
9
|
+
# Add service information about the object in order
|
10
|
+
# to distinguish objects in collection from each other
|
11
|
+
|
12
|
+
unless object.id.nil?
|
13
|
+
messages = messages.merge(id: object.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
unless object.client_id.nil?
|
17
|
+
messages = messages.merge(client_id: object.client_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
messages
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class BetterValidations::NestedValidator < ActiveModel::EachValidator
|
2
|
+
attr_reader :validator_class
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
@validator_class = options.delete(:validator_class)
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def validate_each(record, attr_name, value)
|
10
|
+
return if value.nil?
|
11
|
+
|
12
|
+
validator = init_validator(value)
|
13
|
+
cache_validator(record, attr_name, validator)
|
14
|
+
return if validator_valid?(validator)
|
15
|
+
|
16
|
+
record.errors.add(error_key(attr_name), error_text)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def init_validator(value)
|
22
|
+
# A value can be a single object or a list of objects
|
23
|
+
if value.is_a?(Enumerable)
|
24
|
+
value.map { |object| validator_class.new(object) }
|
25
|
+
else
|
26
|
+
validator_class.new(value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def cache_validator(record, attr_name, validator)
|
31
|
+
record.nested_object_validators[attr_name.to_sym] = validator
|
32
|
+
end
|
33
|
+
|
34
|
+
def validator_valid?(validator)
|
35
|
+
validators = validator.is_a?(Enumerable) ? validator : [validator]
|
36
|
+
validators.map(&:valid?).all?
|
37
|
+
end
|
38
|
+
|
39
|
+
def error_key(attr_name)
|
40
|
+
# Create a key with a dot to tell a framework that an error happened in
|
41
|
+
# a nested object
|
42
|
+
"#{attr_name}.attributes".to_sym
|
43
|
+
end
|
44
|
+
|
45
|
+
def error_text
|
46
|
+
I18n.t('errors.messages.invalid')
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module BetterValidations::Object
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
included do
|
4
|
+
|
5
|
+
# A helper method to get messages without a reference to 'errors'
|
6
|
+
def detailed_errors_messages(wrap_attributes_to)
|
7
|
+
errors.detailed_messages(wrap_attributes_to: wrap_attributes_to)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Define a 'client_id' attribute for ActiveRecord::Base that can
|
11
|
+
# be used to identify objects in the error response.
|
12
|
+
def client_id
|
13
|
+
@client_id
|
14
|
+
end
|
15
|
+
|
16
|
+
# A setter for 'client_id' attribute. Client can pass this attribute
|
17
|
+
# to API and fill it to identify objects in the error response.
|
18
|
+
def client_id=(value)
|
19
|
+
@client_id = value
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns relation object for providing nested messages.
|
23
|
+
# By default it is the object itself.
|
24
|
+
def relation_for_nested_messages(relation)
|
25
|
+
public_send(relation)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module BetterValidations::Validator
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
included do
|
4
|
+
include ActiveModel::Validations
|
5
|
+
include BetterValidations::Object
|
6
|
+
|
7
|
+
# A system accessors required by BetterValidations::Object
|
8
|
+
attr_accessor :id, :client_id
|
9
|
+
|
10
|
+
# A hash with cached instances of nested validators by field.
|
11
|
+
# Filled by instances of a BetterValidations::NestedValidator class
|
12
|
+
# in the process of validation.
|
13
|
+
attr_accessor :nested_object_validators
|
14
|
+
|
15
|
+
# A validation object as a possible data source
|
16
|
+
attr_reader :validation_object
|
17
|
+
|
18
|
+
# A helper method to validate nested object/list
|
19
|
+
# represented by other validator.
|
20
|
+
#
|
21
|
+
# Example of usage in a User model for validating nested PersonalInfo:
|
22
|
+
# validate_nested :personal_info, PersonalInfoValidator
|
23
|
+
def self.validate_nested(nested_name, validator_class)
|
24
|
+
bind_validator(nested_name, validator_class)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Calls a validates_with method to save information about
|
28
|
+
# the validating object to the validator and run validations.
|
29
|
+
def self.bind_validator(nested_name, validator_class)
|
30
|
+
validates_with BetterValidations::NestedValidator,
|
31
|
+
attributes: [nested_name],
|
32
|
+
validator_class: validator_class
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a structure of validators such as:
|
36
|
+
# { field: { kind: true }, nested: { field: { kind: true } } }
|
37
|
+
# where "kind" is a validator kind such as "presence".
|
38
|
+
def self.structure
|
39
|
+
validators_by_field_name.reduce({}) do |structure, (field, validator)|
|
40
|
+
validations = (structure[field] || {}).merge(validator_hash(validator))
|
41
|
+
structure.merge(field => validations)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns an array:
|
46
|
+
# [[:field_one, validator], [:field_two, validator]]
|
47
|
+
# fields can duplicate if have multiple validators.
|
48
|
+
def self.validators_by_field_name
|
49
|
+
validators.map do |validator|
|
50
|
+
validator.attributes.map { |attribute| [attribute, validator] }
|
51
|
+
end.flatten(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns a hash such as:
|
55
|
+
# { kind: true }
|
56
|
+
# where "kind" is a validator kind such as "presence".
|
57
|
+
def self.validator_hash(validator)
|
58
|
+
kind = validator.kind
|
59
|
+
kind == :nested ? validator.validator_class.structure : { kind => true }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Attributes - Hash, ActionController::Parameters or ActiveRecord::Base
|
63
|
+
def initialize(attributes = {})
|
64
|
+
assign_attributes(attributes)
|
65
|
+
end
|
66
|
+
|
67
|
+
def assign_attributes(attributes)
|
68
|
+
prepare_attributes(attributes).each { |key, value| set_value(key, value) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def merge(*validators)
|
72
|
+
BetterValidations::ValidatorsList.new(*([self] + validators))
|
73
|
+
end
|
74
|
+
|
75
|
+
# Override to define a start value and getter by name
|
76
|
+
def nested_object_validators(name = nil)
|
77
|
+
return nested_object_validators[name.to_sym] unless name.nil?
|
78
|
+
|
79
|
+
@nested_object_validators ||= {}
|
80
|
+
end
|
81
|
+
|
82
|
+
# The method is overriden for providing a validator object instead of
|
83
|
+
# an active record to collecting error messages.
|
84
|
+
def relation_for_nested_messages(relation)
|
85
|
+
nested_object_validators(relation.to_sym)
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def prepare_attributes(attributes)
|
91
|
+
if attributes.is_a? ActiveRecord::Base
|
92
|
+
@validation_object = attributes
|
93
|
+
attributes = convert_active_record_to_attributes(attributes)
|
94
|
+
end
|
95
|
+
|
96
|
+
attributes
|
97
|
+
end
|
98
|
+
|
99
|
+
def convert_active_record_to_attributes(object)
|
100
|
+
attribute_names.reduce({}) do |hash, name|
|
101
|
+
hash.merge(name => object.public_send(name))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def attribute_names
|
106
|
+
(self.class.validators.map(&:attributes).flatten + [:client_id, :id]).uniq
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_value(key, value)
|
110
|
+
setter = "#{key}=".to_sym
|
111
|
+
public_send(setter, value) if respond_to?(setter)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Provides a way to merge multiple validators in order to get
|
2
|
+
# merged errors from all of them. Usage:
|
3
|
+
#
|
4
|
+
# validator = validator_one.merge(validator_two, validator_three)
|
5
|
+
# validator.valid?
|
6
|
+
# validator.errors.detailed_messages
|
7
|
+
#
|
8
|
+
class BetterValidations::ValidatorsList
|
9
|
+
def initialize(*validators)
|
10
|
+
@validators = validators
|
11
|
+
end
|
12
|
+
|
13
|
+
def errors
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid?
|
18
|
+
if @invalid_validators.nil?
|
19
|
+
@invalid_validators = @validators.select(&:invalid?)
|
20
|
+
end
|
21
|
+
|
22
|
+
@invalid_validators.blank?
|
23
|
+
end
|
24
|
+
|
25
|
+
def invalid?
|
26
|
+
!valid?
|
27
|
+
end
|
28
|
+
|
29
|
+
def detailed_messages(wrap_attributes_to: nil)
|
30
|
+
(@invalid_validators || []).reduce({}) do |all_messages, validator|
|
31
|
+
messages = validator.errors.detailed_messages(
|
32
|
+
wrap_attributes_to: wrap_attributes_to
|
33
|
+
)
|
34
|
+
|
35
|
+
deep_merge(all_messages, messages)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def deep_merge(hash_one, hash_two)
|
40
|
+
# Use a standard method to do a deep merge by specify
|
41
|
+
# a values concatination logic
|
42
|
+
hash_one.deep_merge(hash_two) do |_key, this_value, other_value|
|
43
|
+
# Arrays has a complex logic - they must be merged
|
44
|
+
if this_value.is_a?(Array) || other_value.is_a?(Array)
|
45
|
+
merge_arrays(this_value, other_value)
|
46
|
+
else
|
47
|
+
this_value.nil? ? other_value : this_value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def merge_arrays(one, two)
|
53
|
+
# If we have arrays of strings it means that we have arrays of errors:
|
54
|
+
# ['Error 1', 'Error 2'] and ['Error 3', 'Error 4']. In this case we
|
55
|
+
# just concat arrays and get unique values.
|
56
|
+
if one.first.is_a?(String) || two.first.is_a?(String)
|
57
|
+
return (one + two).uniq
|
58
|
+
end
|
59
|
+
|
60
|
+
# Other type of arrays is an array of hashes. Each hash is
|
61
|
+
# an object with attributes:
|
62
|
+
# [{ id: 1, client_id: 2, key: "String", another_key: {} }]
|
63
|
+
merge_arrays_with_errors(one, two)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Merges arrays of hashes to a single array by deep merging items
|
67
|
+
# with the same ":id" and ":client_id".
|
68
|
+
def merge_arrays_with_errors(one, two)
|
69
|
+
all = one + two
|
70
|
+
all = merge_hashes_by_key(all, :id)
|
71
|
+
merge_hashes_by_key(all, :client_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
def merge_hashes_by_key(hashes, key)
|
75
|
+
hashes_by_id = hashes.group_by { |hash| hash[key] }
|
76
|
+
hashes_by_id.map do |id, hashes_with_id|
|
77
|
+
next hashes_with_id if id.nil?
|
78
|
+
|
79
|
+
# Merge all hashes with the same id to the single hash.
|
80
|
+
# Wrap to array in order to save a format (hashes_with_id is a array)
|
81
|
+
[hashes_with_id.reduce({}) { |result, hash| deep_merge(result, hash) }]
|
82
|
+
end.flatten(1)
|
83
|
+
end
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: better_validations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Petr Bazov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-04-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7'
|
33
|
+
description: Extension for default Rails validations. Adds some useful methods.
|
34
|
+
email:
|
35
|
+
- petr@sequenia.com
|
36
|
+
executables: []
|
37
|
+
extensions: []
|
38
|
+
extra_rdoc_files: []
|
39
|
+
files:
|
40
|
+
- MIT-LICENSE
|
41
|
+
- README.md
|
42
|
+
- lib/better_validations.rb
|
43
|
+
- lib/better_validations/errors.rb
|
44
|
+
- lib/better_validations/list.rb
|
45
|
+
- lib/better_validations/nested_validator.rb
|
46
|
+
- lib/better_validations/object.rb
|
47
|
+
- lib/better_validations/railtie.rb
|
48
|
+
- lib/better_validations/validator.rb
|
49
|
+
- lib/better_validations/validators_list.rb
|
50
|
+
- lib/better_validations/version.rb
|
51
|
+
homepage: http://sequenia.com/
|
52
|
+
licenses:
|
53
|
+
- MIT
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubygems_version: 3.0.3
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: Extension for default Rails validations.
|
74
|
+
test_files: []
|