errapi 0.1.0 → 0.1.2
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 +4 -4
- data/Gemfile +4 -2
- data/README.md +6 -2
- data/VERSION +1 -1
- data/lib/errapi/condition.rb +71 -0
- data/lib/errapi/configuration.rb +79 -0
- data/lib/errapi/errors.rb +15 -0
- data/lib/errapi/location_builders.rb +17 -0
- data/lib/errapi/locations/dotted.rb +33 -0
- data/lib/errapi/locations/json.rb +33 -0
- data/lib/errapi/locations/none.rb +28 -0
- data/lib/errapi/locations.rb +4 -0
- data/lib/errapi/model.rb +30 -0
- data/lib/errapi/object_validator.rb +230 -0
- data/lib/errapi/plugins/i18n_messages.rb +20 -0
- data/lib/errapi/plugins/location.rb +29 -0
- data/lib/errapi/plugins/reason.rb +22 -0
- data/lib/errapi/plugins.rb +4 -0
- data/lib/errapi/single_validator.rb +19 -0
- data/lib/errapi/utils.rb +12 -0
- data/lib/errapi/validation_context.rb +49 -0
- data/lib/errapi/validation_error.rb +43 -0
- data/lib/errapi/validations/clusivity.rb +45 -0
- data/lib/errapi/validations/exclusion.rb +28 -0
- data/lib/errapi/validations/format.rb +33 -0
- data/lib/errapi/validations/inclusion.rb +28 -0
- data/lib/errapi/validations/length.rb +66 -0
- data/lib/errapi/validations/presence.rb +39 -0
- data/lib/errapi/validations/trim.rb +10 -0
- data/lib/errapi/validations/type.rb +54 -0
- data/lib/errapi/validations.rb +57 -0
- data/lib/errapi/validator_proxy.rb +21 -0
- data/lib/errapi.rb +45 -1
- metadata +63 -7
@@ -0,0 +1,19 @@
|
|
1
|
+
module Errapi
|
2
|
+
|
3
|
+
class SingleValidator
|
4
|
+
|
5
|
+
def self.configure *args, &block
|
6
|
+
|
7
|
+
options = args.last.kind_of?(Hash) ? args.pop : {}
|
8
|
+
config = options[:config] || Errapi.config
|
9
|
+
config = Errapi.config config if config.kind_of? Symbol
|
10
|
+
|
11
|
+
@errapi_validator = ObjectValidator.new config, options, &block
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.validate *args, &block
|
15
|
+
raise "Validator has not yet been configured. You must call #configure before calling #validate." unless @errapi_validator
|
16
|
+
@errapi_validator.validate *args, &block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/errapi/utils.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Errapi::Utils
|
2
|
+
|
3
|
+
def self.camelize string, uppercase_first_letter = false
|
4
|
+
parts = string.split '_'
|
5
|
+
return string if parts.length < 2
|
6
|
+
parts[0] + parts[1, parts.length - 1].collect(&:capitalize).join
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.underscore string
|
10
|
+
string.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class Errapi::ValidationContext
|
4
|
+
attr_reader :data
|
5
|
+
attr_reader :errors
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
def initialize options = {}
|
9
|
+
@errors = []
|
10
|
+
@data = OpenStruct.new options[:data] || {}
|
11
|
+
@config = options[:config]
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_error options = {}, &block
|
15
|
+
|
16
|
+
error = options.kind_of?(Errapi::ValidationError) ? options : @config.new_error(options)
|
17
|
+
yield error if block_given?
|
18
|
+
@config.build_error error, self
|
19
|
+
|
20
|
+
@errors << error
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def errors? criteria = {}, &block
|
25
|
+
return !@errors.empty? if criteria.empty? && !block
|
26
|
+
block ? @errors.any?{ |err| err.matches?(criteria) && block.call(err) } : @errors.any?{ |err| err.matches?(criteria) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid?
|
30
|
+
!errors?
|
31
|
+
end
|
32
|
+
|
33
|
+
def clear
|
34
|
+
@errors.clear
|
35
|
+
@data = OpenStruct.new
|
36
|
+
end
|
37
|
+
|
38
|
+
# TODO: add custom serialization options
|
39
|
+
def serialize
|
40
|
+
# TODO: add hook for plugins to serialize context
|
41
|
+
{ errors: [] }.tap do |h|
|
42
|
+
@errors.each do |error|
|
43
|
+
serialized = {}
|
44
|
+
@config.serialize_error error, serialized
|
45
|
+
h[:errors] << serialized
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class Errapi::ValidationError
|
4
|
+
attr_accessor :reason
|
5
|
+
attr_accessor :check_value
|
6
|
+
attr_accessor :checked_value
|
7
|
+
attr_accessor :validation
|
8
|
+
attr_accessor :constraints
|
9
|
+
attr_accessor :location
|
10
|
+
|
11
|
+
def initialize options = {}
|
12
|
+
ATTRIBUTES.each do |attr|
|
13
|
+
instance_variable_set "@#{attr}", options[attr] if options.key? attr
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches? criteria = {}
|
18
|
+
unknown_criteria = criteria.keys - ATTRIBUTES
|
19
|
+
raise "Unknown error attributes: #{unknown_criteria.join(', ')}." if unknown_criteria.any?
|
20
|
+
ATTRIBUTES.all?{ |attr| criterion_matches? criteria, attr }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
ATTRIBUTES = %i(reason location check_value checked_value validation)
|
26
|
+
|
27
|
+
def criterion_matches? criteria, attr
|
28
|
+
return true unless criteria.key? attr
|
29
|
+
|
30
|
+
value = send attr
|
31
|
+
criterion = criteria[attr]
|
32
|
+
|
33
|
+
if criterion.kind_of? Regexp
|
34
|
+
!!criterion.match(value.to_s)
|
35
|
+
elsif criterion.kind_of? String
|
36
|
+
criterion == value.to_s
|
37
|
+
elsif criterion.respond_to? :===
|
38
|
+
criterion === value
|
39
|
+
else
|
40
|
+
criterion == value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Errapi::Validations
|
2
|
+
module Clusivity
|
3
|
+
private
|
4
|
+
|
5
|
+
DELIMITER_METHOD_CHECKS = %i(include? call to_sym).freeze
|
6
|
+
|
7
|
+
def check_delimiter! option_desc
|
8
|
+
unless @delimiter.respond_to?(:include?) || callable_option_value?(@delimiter)
|
9
|
+
raise callable_option_type_error option_desc, "an object with the #include? method", @delimiter
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def members option_desc, options = {}
|
14
|
+
enumerable = actual_option_value @delimiter, options
|
15
|
+
|
16
|
+
unless enumerable.respond_to? :include?
|
17
|
+
raise callable_option_value_error option_desc, "an object with the #include? method", @delimiter
|
18
|
+
end
|
19
|
+
|
20
|
+
enumerable
|
21
|
+
end
|
22
|
+
|
23
|
+
def include? members, value
|
24
|
+
members.send inclusion_method(members), value
|
25
|
+
end
|
26
|
+
|
27
|
+
# From rails/activemodel/lib/active_model/validations/clusivity.rb:
|
28
|
+
# In Ruby 1.9 <tt>Range#include?</tt> on non-number-or-time-ish ranges checks all
|
29
|
+
# possible values in the range for equality, which is slower but more accurate.
|
30
|
+
# <tt>Range#cover?</tt> uses the previous logic of comparing a value with the range
|
31
|
+
# endpoints, which is fast but is only accurate on Numeric, Time, or DateTime ranges.
|
32
|
+
def inclusion_method enumerable
|
33
|
+
if enumerable.is_a? Range
|
34
|
+
case enumerable.first
|
35
|
+
when Numeric, Time, DateTime
|
36
|
+
:cover?
|
37
|
+
else
|
38
|
+
:include?
|
39
|
+
end
|
40
|
+
else
|
41
|
+
:include?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'clusivity.rb')
|
2
|
+
|
3
|
+
module Errapi::Validations
|
4
|
+
class Exclusion < Base
|
5
|
+
include Clusivity
|
6
|
+
|
7
|
+
def initialize options = {}
|
8
|
+
unless key = exactly_one_option?(OPTIONS, options)
|
9
|
+
raise ArgumentError, "Either :from or :in or :within must be supplied (but only one of them)."
|
10
|
+
end
|
11
|
+
|
12
|
+
@delimiter = options[key]
|
13
|
+
check_delimiter! OPTIONS_DESCRIPTION
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate value, context, options = {}
|
17
|
+
excluded_values = members OPTIONS_DESCRIPTION, options
|
18
|
+
if include? excluded_values, value
|
19
|
+
context.add_error reason: :excluded, check_value: excluded_values
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
OPTIONS = %i(from in within)
|
26
|
+
OPTIONS_DESCRIPTION = ":from (or :in or :within)"
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Errapi::Validations
|
2
|
+
class Format < Base
|
3
|
+
|
4
|
+
def initialize options = {}
|
5
|
+
unless key = exactly_one_option?(OPTIONS, options)
|
6
|
+
raise ArgumentError, "Either :with or :without must be supplied (but not both)."
|
7
|
+
end
|
8
|
+
|
9
|
+
@format = options[key]
|
10
|
+
@should_match = key == :with
|
11
|
+
|
12
|
+
unless @format.kind_of?(Regexp) or callable_option_value?(@format)
|
13
|
+
raise callable_option_type_error ":with (or :without)", "a regular expression", @format
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate value, context, options = {}
|
18
|
+
|
19
|
+
regexp = actual_option_value @format, options
|
20
|
+
unless regexp.kind_of? Regexp
|
21
|
+
raise callable_option_value_error ":with (or :without)", "a regular expression", regexp
|
22
|
+
end
|
23
|
+
|
24
|
+
if !regexp.match(value.to_s) == @should_match
|
25
|
+
context.add_error reason: :invalid_format, check_value: regexp
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
OPTIONS = %i(with without)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'clusivity.rb')
|
2
|
+
|
3
|
+
module Errapi::Validations
|
4
|
+
class Inclusion < Base
|
5
|
+
include Clusivity
|
6
|
+
|
7
|
+
def initialize options = {}
|
8
|
+
unless key = exactly_one_option?(OPTIONS, options)
|
9
|
+
raise ArgumentError, "Either :in or :within must be supplied (but not both)."
|
10
|
+
end
|
11
|
+
|
12
|
+
@delimiter = options[key]
|
13
|
+
check_delimiter! OPTIONS_DESCRIPTION
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate value, context, options = {}
|
17
|
+
allowed_values = members OPTIONS_DESCRIPTION, options
|
18
|
+
unless include? allowed_values, value
|
19
|
+
context.add_error reason: :not_included, check_value: allowed_values
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
OPTIONS = %i(in within)
|
26
|
+
OPTIONS_DESCRIPTION = ":in (or :within)"
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Errapi::Validations
|
2
|
+
class Length < Base
|
3
|
+
CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze
|
4
|
+
REASONS = { is: :wrong_length, minimum: :too_short, maximum: :too_long }.freeze
|
5
|
+
|
6
|
+
def initialize options = {}
|
7
|
+
|
8
|
+
constraints = options.select{ |k,v| OPTIONS.include? k }
|
9
|
+
if constraints.empty?
|
10
|
+
raise ArgumentError, "The :is, :minimum/:maximum or :within options must be supplied (but only :minimum and :maximum can be used together)."
|
11
|
+
elsif options.key?(:is) && constraints.length != 1
|
12
|
+
raise ArgumentError, "The :is option cannot be combined with :minimum, :maximum or :within."
|
13
|
+
elsif options.key?(:is)
|
14
|
+
check_numeric! options[:is]
|
15
|
+
elsif options.key?(:within)
|
16
|
+
if options.key?(:minimum) || options.key?(:maximum)
|
17
|
+
raise ArgumentError, "The :within option cannot be combined with :minimum or :maximum."
|
18
|
+
else
|
19
|
+
check_range! options[:within]
|
20
|
+
end
|
21
|
+
else
|
22
|
+
check_numeric! options[:minimum] if options.key? :minimum
|
23
|
+
check_numeric! options[:maximum] if options.key? :maximum
|
24
|
+
end
|
25
|
+
|
26
|
+
@constraints = actual_constraints constraints
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate value, context, options = {}
|
30
|
+
return unless value.respond_to? :length
|
31
|
+
actual_length = value.length
|
32
|
+
|
33
|
+
CHECKS.each_pair do |key,check|
|
34
|
+
next unless check_value = @constraints[key]
|
35
|
+
next if actual_length.send check, check_value
|
36
|
+
context.add_error reason: REASONS[key], check_value: check_value, checked_value: actual_length, constraints: @constraints
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
OPTIONS = %i(is minimum maximum within)
|
43
|
+
|
44
|
+
def actual_constraints options = {}
|
45
|
+
if range = options[:within]
|
46
|
+
{ minimum: range.min, maximum: range.max }
|
47
|
+
else
|
48
|
+
options
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_numeric! bound
|
53
|
+
unless bound.kind_of? Numeric
|
54
|
+
raise ArgumentError, "The :is, :minimum or :maximum option must be a numeric value, but a #{bound.class.name} was given."
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def check_range! range
|
59
|
+
if !range.kind_of?(Range)
|
60
|
+
raise ArgumentError, "The :within option must be a numeric range, but a #{range.class.name} was given."
|
61
|
+
elsif !(t = range.first).kind_of?(Numeric)
|
62
|
+
raise ArgumentError, "The :within option must be a numeric range, but a #{t.class.name} range was given."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Errapi::Validations
|
2
|
+
class Presence < Factory
|
3
|
+
class Implementation < Base
|
4
|
+
|
5
|
+
def validate value, context, options = {}
|
6
|
+
if reason = check(value, options.fetch(:value_set, true))
|
7
|
+
context.add_error reason: reason
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
BLANK_REGEXP = /\A[[:space:]]*\z/
|
14
|
+
|
15
|
+
def check value, value_set
|
16
|
+
# TODO: allow customization (e.g. values that are not required, booleans, etc)
|
17
|
+
if !value_set
|
18
|
+
:missing
|
19
|
+
elsif value.nil?
|
20
|
+
:null
|
21
|
+
elsif value.respond_to?(:empty?) && value.empty?
|
22
|
+
:empty
|
23
|
+
elsif value_blank? value
|
24
|
+
:blank
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def value_blank? value
|
29
|
+
if value.respond_to? :blank?
|
30
|
+
value.blank?
|
31
|
+
elsif value.kind_of? String
|
32
|
+
BLANK_REGEXP === value
|
33
|
+
else
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Errapi::Validations
|
2
|
+
class Type < Base
|
3
|
+
|
4
|
+
def initialize options = {}
|
5
|
+
unless key = exactly_one_option?(OPTIONS, options)
|
6
|
+
raise ArgumentError, "One option among :instance_of, :kind_of, :is_a or :is_an must be supplied (but only one)."
|
7
|
+
end
|
8
|
+
|
9
|
+
if key == :instance_of
|
10
|
+
@instance_of = check_types! options[key]
|
11
|
+
raise ArgumentError, "Type aliases cannot be used with the :instance_of option. Use :kind_of, :is_a or :is_an." if options[key].kind_of? Symbol
|
12
|
+
else
|
13
|
+
@kind_of = check_types! options[key]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate value, context, options = {}
|
18
|
+
if @instance_of && @instance_of.none?{ |type| value.instance_of? type }
|
19
|
+
context.add_error reason: :wrong_type, check_value: @instance_of, checked_value: value.class
|
20
|
+
elsif @kind_of && @kind_of.none?{ |type| value.kind_of? type }
|
21
|
+
context.add_error reason: :wrong_type, check_value: @kind_of, checked_value: value.class
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def check_types! types
|
28
|
+
if !types.kind_of?(Array)
|
29
|
+
types = [ types ]
|
30
|
+
elsif types.empty?
|
31
|
+
raise ArgumentError, "At least one class or module is required, but an empty array was given."
|
32
|
+
end
|
33
|
+
|
34
|
+
types.each do |type|
|
35
|
+
unless TYPE_ALIASES.key?(type) || type.class == Class || type.class == Module
|
36
|
+
raise ArgumentError, "A class or module (or an array of classes or modules, or a type alias) is required, but a #{type.class} was given."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
types.collect{ |type| TYPE_ALIASES[type] || type }.flatten.uniq
|
41
|
+
end
|
42
|
+
|
43
|
+
OPTIONS = %i(instance_of kind_of is_a is_an)
|
44
|
+
TYPE_ALIASES = {
|
45
|
+
string: [ String ],
|
46
|
+
number: [ Numeric ],
|
47
|
+
integer: [ Integer ],
|
48
|
+
boolean: [ TrueClass, FalseClass ],
|
49
|
+
object: [ Hash ],
|
50
|
+
array: [ Array ],
|
51
|
+
null: [ NilClass ]
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Errapi::Validations
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def initialize options = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def actual_option_value supplied_value, options
|
9
|
+
if supplied_value.respond_to? :call
|
10
|
+
supplied_value.call options[:source]
|
11
|
+
elsif supplied_value.respond_to? :to_sym
|
12
|
+
unless options[:source].respond_to? supplied_value
|
13
|
+
raise ArgumentError, "The validation source (#{options[:source].class.name}) does not respond to :#{supplied_value}."
|
14
|
+
else
|
15
|
+
options[:source].send supplied_value
|
16
|
+
end
|
17
|
+
else
|
18
|
+
supplied_value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def callable_option_value? supplied_value
|
23
|
+
supplied_value.respond_to?(:call) || supplied_value.respond_to?(:to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def exactly_one_option? keys, options
|
27
|
+
found_keys = options.keys.select{ |k| keys.include? k }
|
28
|
+
found_keys.length == 1 ? found_keys.first : false
|
29
|
+
end
|
30
|
+
|
31
|
+
def callable_option_type_error key_desc, value_desc, supplied_value
|
32
|
+
ArgumentError.new "The #{key_desc} option must be #{value_desc}, a proc, a lambda or a symbol, but a #{supplied_value.class.name} was given."
|
33
|
+
end
|
34
|
+
|
35
|
+
def callable_option_value_error key_desc, type_desc, supplied_value
|
36
|
+
ArgumentError.new "The call supplied to #{key_desc} must return #{type_desc}, but a #{supplied_value.class.name} was returned."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Factory
|
41
|
+
|
42
|
+
def config= config
|
43
|
+
raise "A configuration has already been set for this factory." if @config
|
44
|
+
@config = config
|
45
|
+
end
|
46
|
+
|
47
|
+
def validation options = {}
|
48
|
+
self.class.const_get('Implementation').new options
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
Errapi::Utils.underscore self.class.name.sub(/.*::/, '')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Errapi
|
2
|
+
|
3
|
+
class ValidatorProxy
|
4
|
+
instance_methods.each{ |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
|
5
|
+
|
6
|
+
def initialize object, validator
|
7
|
+
@object = object
|
8
|
+
@validator = validator
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate context, options = {}
|
12
|
+
@validator.validate @object, context, options
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def method_missing name, *args, &block
|
18
|
+
@validator.send name, *args, &block
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/errapi.rb
CHANGED
@@ -1,3 +1,47 @@
|
|
1
1
|
module Errapi
|
2
|
-
VERSION = '0.1.
|
2
|
+
VERSION = '0.1.2'
|
3
|
+
end
|
4
|
+
|
5
|
+
Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
|
6
|
+
|
7
|
+
module Errapi
|
8
|
+
|
9
|
+
def self.configure name = nil, &block
|
10
|
+
|
11
|
+
init_configs
|
12
|
+
name ||= :default
|
13
|
+
|
14
|
+
if @configs[name]
|
15
|
+
@configs[name].configure &block
|
16
|
+
else
|
17
|
+
@configs[name] = Configuration.new &block
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.config name = nil
|
22
|
+
init_configs[name || :default]
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.init_configs
|
28
|
+
@configs ? @configs : @configs = { default: default_config }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.default_config
|
32
|
+
Configuration.new.tap do |config|
|
33
|
+
config.plugin Errapi::Plugins::I18nMessages
|
34
|
+
config.plugin Errapi::Plugins::Reason
|
35
|
+
config.plugin Errapi::Plugins::Location
|
36
|
+
config.validation_factory Errapi::Validations::Exclusion
|
37
|
+
config.validation_factory Errapi::Validations::Format
|
38
|
+
config.validation_factory Errapi::Validations::Inclusion
|
39
|
+
config.validation_factory Errapi::Validations::Length
|
40
|
+
config.validation_factory Errapi::Validations::Presence.new
|
41
|
+
config.validation_factory Errapi::Validations::Trim
|
42
|
+
config.validation_factory Errapi::Validations::Type
|
43
|
+
config.register_condition Errapi::Condition::SimpleCheck
|
44
|
+
config.register_condition Errapi::Condition::ErrorCheck
|
45
|
+
end
|
46
|
+
end
|
3
47
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: errapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Oulevay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: i18n
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.7.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.7.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rake
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,20 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '3.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-collection_matchers
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.1'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: jeweler
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,28 +100,28 @@ dependencies:
|
|
72
100
|
requirements:
|
73
101
|
- - "~>"
|
74
102
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
103
|
+
version: 0.9.1
|
76
104
|
type: :development
|
77
105
|
prerelease: false
|
78
106
|
version_requirements: !ruby/object:Gem::Requirement
|
79
107
|
requirements:
|
80
108
|
- - "~>"
|
81
109
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
110
|
+
version: 0.9.1
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: coveralls
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
86
114
|
requirements:
|
87
115
|
- - "~>"
|
88
116
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
117
|
+
version: 0.7.3
|
90
118
|
type: :development
|
91
119
|
prerelease: false
|
92
120
|
version_requirements: !ruby/object:Gem::Requirement
|
93
121
|
requirements:
|
94
122
|
- - "~>"
|
95
123
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
124
|
+
version: 0.7.3
|
97
125
|
description: Utilities to validate data and serialize errors.
|
98
126
|
email: git@alphahydrae.com
|
99
127
|
executables: []
|
@@ -107,6 +135,34 @@ files:
|
|
107
135
|
- README.md
|
108
136
|
- VERSION
|
109
137
|
- lib/errapi.rb
|
138
|
+
- lib/errapi/condition.rb
|
139
|
+
- lib/errapi/configuration.rb
|
140
|
+
- lib/errapi/errors.rb
|
141
|
+
- lib/errapi/location_builders.rb
|
142
|
+
- lib/errapi/locations.rb
|
143
|
+
- lib/errapi/locations/dotted.rb
|
144
|
+
- lib/errapi/locations/json.rb
|
145
|
+
- lib/errapi/locations/none.rb
|
146
|
+
- lib/errapi/model.rb
|
147
|
+
- lib/errapi/object_validator.rb
|
148
|
+
- lib/errapi/plugins.rb
|
149
|
+
- lib/errapi/plugins/i18n_messages.rb
|
150
|
+
- lib/errapi/plugins/location.rb
|
151
|
+
- lib/errapi/plugins/reason.rb
|
152
|
+
- lib/errapi/single_validator.rb
|
153
|
+
- lib/errapi/utils.rb
|
154
|
+
- lib/errapi/validation_context.rb
|
155
|
+
- lib/errapi/validation_error.rb
|
156
|
+
- lib/errapi/validations.rb
|
157
|
+
- lib/errapi/validations/clusivity.rb
|
158
|
+
- lib/errapi/validations/exclusion.rb
|
159
|
+
- lib/errapi/validations/format.rb
|
160
|
+
- lib/errapi/validations/inclusion.rb
|
161
|
+
- lib/errapi/validations/length.rb
|
162
|
+
- lib/errapi/validations/presence.rb
|
163
|
+
- lib/errapi/validations/trim.rb
|
164
|
+
- lib/errapi/validations/type.rb
|
165
|
+
- lib/errapi/validator_proxy.rb
|
110
166
|
homepage: http://github.com/AlphaHydrae/errapi
|
111
167
|
licenses:
|
112
168
|
- MIT
|
@@ -127,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
183
|
version: '0'
|
128
184
|
requirements: []
|
129
185
|
rubyforge_project:
|
130
|
-
rubygems_version: 2.
|
186
|
+
rubygems_version: 2.4.3
|
131
187
|
signing_key:
|
132
188
|
specification_version: 4
|
133
189
|
summary: An extensible API-oriented validation library.
|