errapi 0.1.2 → 0.1.3
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/VERSION +1 -1
- data/lib/errapi.rb +27 -22
- data/lib/errapi/configuration.rb +49 -4
- data/lib/errapi/object_validator.rb +11 -2
- data/lib/errapi/plugins.rb +10 -0
- data/lib/errapi/plugins/i18n_messages.rb +3 -2
- data/lib/errapi/plugins/location.rb +19 -19
- data/lib/errapi/plugins/reason.rb +15 -15
- data/lib/errapi/validations.rb +25 -6
- data/lib/errapi/validations/exclusion.rb +4 -0
- data/lib/errapi/validations/format.rb +3 -0
- data/lib/errapi/validations/inclusion.rb +4 -0
- data/lib/errapi/validations/length.rb +4 -0
- data/lib/errapi/validations/presence.rb +28 -27
- data/lib/errapi/validations/trim.rb +3 -0
- data/lib/errapi/validations/type.rb +3 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 544cdac914cba1a85759631310e365ffebf9c821
|
4
|
+
data.tar.gz: d33e3f71d0a276dea1d45e767b44db39f96b4e98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12c749f8d759cc133a292a54d1565838740db17b7bb6127893da00faab32a814bd680ef8f68d313f84386dbb8f91f5861af986bb2fa5cf21fb217067e5170059
|
7
|
+
data.tar.gz: a53453d8aebf3bda928c582d9c02645e1579efe83269a9e1403ce80af91c2458e2637e3096c5eda25123da869be3f86c923d0dbe2c2e6999ddeddca66481d8ee
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/lib/errapi.rb
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
module Errapi
|
2
|
-
VERSION = '0.1.
|
2
|
+
VERSION = '0.1.3'
|
3
3
|
end
|
4
4
|
|
5
5
|
Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
|
6
6
|
|
7
7
|
module Errapi
|
8
8
|
|
9
|
-
def self.configure
|
9
|
+
def self.configure *args, &block
|
10
10
|
|
11
|
-
|
12
|
-
name
|
11
|
+
options = args.last.kind_of?(Hash) ? args.pop : {}
|
12
|
+
name = args.shift || :default
|
13
13
|
|
14
|
+
init_configs
|
14
15
|
if @configs[name]
|
15
|
-
|
16
|
+
raise ArgumentError, %/Configuration "#{name}" has already been configured./
|
16
17
|
else
|
17
|
-
@configs[name] = Configuration.new
|
18
|
+
@configs[name] = options[:config] || Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
if options.fetch :defaults, true
|
22
|
+
default_config! @configs[name]
|
18
23
|
end
|
24
|
+
|
25
|
+
@configs[name].configure &block
|
19
26
|
end
|
20
27
|
|
21
28
|
def self.config name = nil
|
@@ -25,23 +32,21 @@ module Errapi
|
|
25
32
|
private
|
26
33
|
|
27
34
|
def self.init_configs
|
28
|
-
@configs ? @configs : @configs = {
|
35
|
+
@configs ? @configs : @configs = {}
|
29
36
|
end
|
30
37
|
|
31
|
-
def self.default_config
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
config.register_condition Errapi::Condition::ErrorCheck
|
45
|
-
end
|
38
|
+
def self.default_config! config
|
39
|
+
config.plugin Errapi::Plugins::I18nMessages.new
|
40
|
+
config.plugin Errapi::Plugins::Reason.new
|
41
|
+
config.plugin Errapi::Plugins::Location.new
|
42
|
+
config.validation_factory Errapi::Validations::Exclusion::Factory.new
|
43
|
+
config.validation_factory Errapi::Validations::Format::Factory.new
|
44
|
+
config.validation_factory Errapi::Validations::Inclusion::Factory.new
|
45
|
+
config.validation_factory Errapi::Validations::Length::Factory.new
|
46
|
+
config.validation_factory Errapi::Validations::Presence::Factory.new
|
47
|
+
config.validation_factory Errapi::Validations::Trim::Factory.new
|
48
|
+
config.validation_factory Errapi::Validations::Type::Factory.new
|
49
|
+
config.condition_factory Errapi::Condition::SimpleCheck
|
50
|
+
config.condition_factory Errapi::Condition::ErrorCheck
|
46
51
|
end
|
47
52
|
end
|
data/lib/errapi/configuration.rb
CHANGED
@@ -12,10 +12,29 @@ module Errapi
|
|
12
12
|
@validation_factories = {}
|
13
13
|
@condition_factories = {}
|
14
14
|
@location_factories = {}
|
15
|
+
@configured = false
|
16
|
+
@configured_blocks = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def configured?
|
20
|
+
@configured
|
15
21
|
end
|
16
22
|
|
17
23
|
def configure
|
18
|
-
|
24
|
+
raise "Configuration can only be done once." if @configured
|
25
|
+
yield self if block_given?
|
26
|
+
@configured_blocks.each{ |block| block.call }
|
27
|
+
@configured_blocks.clear
|
28
|
+
@configured = true
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_configured &block
|
33
|
+
if @configured
|
34
|
+
block.call
|
35
|
+
else
|
36
|
+
@configured_blocks << block
|
37
|
+
end
|
19
38
|
end
|
20
39
|
|
21
40
|
def new_error options = {}
|
@@ -35,30 +54,46 @@ module Errapi
|
|
35
54
|
end
|
36
55
|
|
37
56
|
def plugin impl, options = {}
|
38
|
-
name =
|
57
|
+
name = implementation_name impl, options
|
39
58
|
impl.config = self if impl.respond_to? :config=
|
40
59
|
@plugins[name] = impl
|
41
60
|
end
|
42
61
|
|
62
|
+
def remove_plugin name
|
63
|
+
raise ArgumentError, "No plugin registered for name #{name.inspect}" unless @plugins.key? name
|
64
|
+
@plugins.delete name
|
65
|
+
end
|
66
|
+
|
43
67
|
def validation_factory factory, options = {}
|
44
|
-
name =
|
68
|
+
name = implementation_name factory, options
|
45
69
|
factory.config = self if factory.respond_to? :config=
|
46
70
|
@validation_factories[name] = factory
|
47
71
|
end
|
48
72
|
|
73
|
+
def remove_validation_factory name
|
74
|
+
raise ArgumentError, "No validation factory registered for name #{name.inspect}" unless @validation_factories.key? name
|
75
|
+
@validation_factories.delete name
|
76
|
+
end
|
77
|
+
|
49
78
|
def validation name, options = {}
|
50
79
|
raise ArgumentError, "No validation factory registered for name #{name.inspect}" unless @validation_factories.key? name
|
51
80
|
factory = @validation_factories[name]
|
52
81
|
factory.respond_to?(:validation) ? factory.validation(options) : factory.new(options)
|
53
82
|
end
|
54
83
|
|
55
|
-
def
|
84
|
+
def condition_factory factory
|
56
85
|
factory.conditionals.each do |conditional|
|
57
86
|
raise ArgumentError, "Conditional #{conditional} should start with 'if' or 'unless'." unless conditional.to_s.match /^(if|unless)/
|
58
87
|
@condition_factories[conditional] = factory
|
59
88
|
end
|
60
89
|
end
|
61
90
|
|
91
|
+
def remove_condition_factory factory
|
92
|
+
factory.conditionals.each do |conditional|
|
93
|
+
@condition_factories.delete conditional
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
62
97
|
def extract_conditions! source, options = {}
|
63
98
|
[].tap do |conditions|
|
64
99
|
@condition_factories.each_pair do |conditional,factory|
|
@@ -70,6 +105,16 @@ module Errapi
|
|
70
105
|
|
71
106
|
private
|
72
107
|
|
108
|
+
def implementation_name impl, options = {}
|
109
|
+
if options[:name]
|
110
|
+
options[:name].to_sym
|
111
|
+
elsif impl.respond_to? :name
|
112
|
+
impl.name.to_sym
|
113
|
+
else
|
114
|
+
raise ArgumentError, "Plugins and factories added to a configuration must respond to #name or be supplied with the :name option."
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
73
118
|
def apply_plugins operation, *args
|
74
119
|
@plugins.each_pair do |name,plugin|
|
75
120
|
plugin.send operation, *args if plugin.respond_to? operation
|
@@ -5,14 +5,18 @@ module Errapi
|
|
5
5
|
class ObjectValidator
|
6
6
|
include LocationBuilders
|
7
7
|
|
8
|
+
# TODO: remove "options" or if used, pass them to new validators instantiated in #register_validations
|
8
9
|
def initialize config, options = {}, &block
|
9
|
-
# TODO: remove these options or if used, pass them to new validators instantiated in #register_validations
|
10
10
|
@config = config
|
11
11
|
@validations = []
|
12
|
-
|
12
|
+
|
13
|
+
@config.on_configured do
|
14
|
+
instance_eval &block if block
|
15
|
+
end
|
13
16
|
end
|
14
17
|
|
15
18
|
def validates *args, &block
|
19
|
+
check_config!
|
16
20
|
register_validations *args, &block
|
17
21
|
end
|
18
22
|
|
@@ -27,6 +31,7 @@ module Errapi
|
|
27
31
|
end
|
28
32
|
|
29
33
|
def validate value, context, options = {}
|
34
|
+
check_config!
|
30
35
|
# TODO: skip validation by default if previous errors at current location
|
31
36
|
# TODO: add support for previous value and skip validation by default if value is unchanged
|
32
37
|
|
@@ -186,6 +191,10 @@ module Errapi
|
|
186
191
|
@validations << validations_definition
|
187
192
|
end
|
188
193
|
|
194
|
+
def check_config!
|
195
|
+
raise "Configuration has not been done. You must call Errapi.config to complete the configuration process." unless @config.configured?
|
196
|
+
end
|
197
|
+
|
189
198
|
class ContextProxy
|
190
199
|
instance_methods.each{ |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
|
191
200
|
attr_accessor :current_location
|
data/lib/errapi/plugins.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Errapi::Plugins
|
2
|
+
class Base
|
3
|
+
|
4
|
+
def self.plugin_name name = nil
|
5
|
+
name ? @name = name : @name
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
self.class.name
|
10
|
+
end
|
11
|
+
end
|
2
12
|
end
|
3
13
|
|
4
14
|
Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'i18n'
|
2
2
|
|
3
3
|
# TODO: support interpolating source and target name (e.g. "Project name cannot be null.")
|
4
|
-
|
5
|
-
class
|
4
|
+
module Errapi::Plugins
|
5
|
+
class I18nMessages < Base
|
6
|
+
plugin_name :message
|
6
7
|
|
7
8
|
def serialize_error error, serialized
|
8
9
|
return if serialized.key? :message
|
@@ -1,29 +1,29 @@
|
|
1
|
-
module Errapi
|
2
|
-
class
|
3
|
-
|
4
|
-
attr_writer :config
|
5
|
-
attr_accessor :camelize
|
1
|
+
module Errapi::Plugins
|
2
|
+
class Location < Base
|
3
|
+
plugin_name :location
|
6
4
|
|
7
|
-
|
8
|
-
|
5
|
+
attr_writer :config
|
6
|
+
attr_accessor :camelize
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
def serialize_error error, serialized
|
9
|
+
if error.location && error.location.respond_to?(:serialize)
|
10
|
+
|
11
|
+
serialized_location = error.location.serialize
|
12
|
+
unless serialized_location.nil?
|
13
|
+
serialized[:location] = serialized_location
|
14
|
+
serialized[location_type_key] = error.location.location_type if error.location.respond_to? :location_type
|
15
15
|
end
|
16
16
|
end
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
+
private
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
def location_type_key
|
22
|
+
camelize? ? :locationType : :location_type
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
25
|
+
def camelize?
|
26
|
+
@camelize.nil? ? @config.options.camelize : @camelize
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -1,22 +1,22 @@
|
|
1
|
-
module Errapi
|
2
|
-
class
|
3
|
-
|
4
|
-
attr_writer :config
|
5
|
-
attr_accessor :camelize
|
1
|
+
module Errapi::Plugins
|
2
|
+
class Reason < Base
|
3
|
+
plugin_name :reason
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
attr_writer :config
|
6
|
+
attr_accessor :camelize
|
10
7
|
|
11
|
-
|
8
|
+
def serialize_error error, serialized
|
9
|
+
serialized[:reason] = serialized_reason error
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def serialized_reason error
|
15
|
+
camelize? ? Utils.camelize(error.reason.to_s).to_sym : error.reason
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
18
|
+
def camelize?
|
19
|
+
@camelize.nil? ? @config.options.camelize : @camelize
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
data/lib/errapi/validations.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'utils.rb')
|
2
|
+
|
1
3
|
module Errapi::Validations
|
2
4
|
|
3
5
|
class Base
|
@@ -37,7 +39,28 @@ module Errapi::Validations
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
class
|
42
|
+
class ValidationFactory
|
43
|
+
|
44
|
+
def self.build impl, options = {}
|
45
|
+
@validation_class = impl
|
46
|
+
@name = options[:name] || Errapi::Utils.underscore(impl.to_s.sub(/.*::/, '')).to_sym
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.name
|
50
|
+
@name
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
self.class.name
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.validation_class
|
58
|
+
@validation_class
|
59
|
+
end
|
60
|
+
|
61
|
+
def validation_class
|
62
|
+
self.class.validation_class
|
63
|
+
end
|
41
64
|
|
42
65
|
def config= config
|
43
66
|
raise "A configuration has already been set for this factory." if @config
|
@@ -45,11 +68,7 @@ module Errapi::Validations
|
|
45
68
|
end
|
46
69
|
|
47
70
|
def validation options = {}
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
def to_s
|
52
|
-
Errapi::Utils.underscore self.class.name.sub(/.*::/, '')
|
71
|
+
validation_class.new options
|
53
72
|
end
|
54
73
|
end
|
55
74
|
end
|
@@ -1,38 +1,39 @@
|
|
1
1
|
module Errapi::Validations
|
2
|
-
class Presence <
|
3
|
-
class
|
2
|
+
class Presence < Base
|
3
|
+
class Factory < ValidationFactory
|
4
|
+
build Presence
|
5
|
+
end
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
7
|
+
def validate value, context, options = {}
|
8
|
+
if reason = check(value, options.fetch(:value_set, true))
|
9
|
+
context.add_error reason: reason
|
9
10
|
end
|
11
|
+
end
|
10
12
|
|
11
|
-
|
13
|
+
private
|
12
14
|
|
13
|
-
|
15
|
+
BLANK_REGEXP = /\A[[:space:]]*\z/
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
17
|
+
def check value, value_set
|
18
|
+
# TODO: allow customization (e.g. values that are not required, booleans, etc)
|
19
|
+
if !value_set
|
20
|
+
:missing
|
21
|
+
elsif value.nil?
|
22
|
+
:null
|
23
|
+
elsif value.respond_to?(:empty?) && value.empty?
|
24
|
+
:empty
|
25
|
+
elsif value_blank? value
|
26
|
+
:blank
|
26
27
|
end
|
28
|
+
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
30
|
+
def value_blank? value
|
31
|
+
if value.respond_to? :blank?
|
32
|
+
value.blank?
|
33
|
+
elsif value.kind_of? String
|
34
|
+
BLANK_REGEXP === value
|
35
|
+
else
|
36
|
+
false
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Oulevay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|