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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dcae888fc36cd422f1fda237dd5381aa10e776d1
4
- data.tar.gz: 757ad4e09cea3666e7279d59d544ff2e99c6bab4
3
+ metadata.gz: 544cdac914cba1a85759631310e365ffebf9c821
4
+ data.tar.gz: d33e3f71d0a276dea1d45e767b44db39f96b4e98
5
5
  SHA512:
6
- metadata.gz: 5fe74be1e6ef55493f04accf713edfc0ce497c982dc84d68e92262bc7183f4d4076fd872d53f15b27a782e7f613054dc76fd8f26c9f2ef95842cfc9bb020c5a3
7
- data.tar.gz: 3ff0b1fee2094513a11daf6ef7d8eb12155a23cadcb4d318843d1bb57dbae2e6c4cf570dac8e1015343a50acf928ccaa4c91da8ad3800b4a92075369124d9c2b
6
+ metadata.gz: 12c749f8d759cc133a292a54d1565838740db17b7bb6127893da00faab32a814bd680ef8f68d313f84386dbb8f91f5861af986bb2fa5cf21fb217067e5170059
7
+ data.tar.gz: a53453d8aebf3bda928c582d9c02645e1579efe83269a9e1403ce80af91c2458e2637e3096c5eda25123da869be3f86c923d0dbe2c2e6999ddeddca66481d8ee
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
data/lib/errapi.rb CHANGED
@@ -1,21 +1,28 @@
1
1
  module Errapi
2
- VERSION = '0.1.2'
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 name = nil, &block
9
+ def self.configure *args, &block
10
10
 
11
- init_configs
12
- name ||= :default
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
- @configs[name].configure &block
16
+ raise ArgumentError, %/Configuration "#{name}" has already been configured./
16
17
  else
17
- @configs[name] = Configuration.new &block
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 = { default: default_config }
35
+ @configs ? @configs : @configs = {}
29
36
  end
30
37
 
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
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
@@ -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
- yield self
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 = options[:name] || Utils.underscore(impl.to_s.sub(/.*::/, '')).to_sym
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 = options[:name] || Utils.underscore(factory.to_s.sub(/.*::/, '')).to_sym
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 register_condition factory
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
- instance_eval &block if block
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
@@ -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
- class Errapi::Plugins::I18nMessages
5
- class << self
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 Plugins::Location
3
- class << self
4
- attr_writer :config
5
- attr_accessor :camelize
1
+ module Errapi::Plugins
2
+ class Location < Base
3
+ plugin_name :location
6
4
 
7
- def serialize_error error, serialized
8
- if error.location && error.location.respond_to?(:serialize)
5
+ attr_writer :config
6
+ attr_accessor :camelize
9
7
 
10
- serialized_location = error.location.serialize
11
- unless serialized_location.nil?
12
- serialized[:location] = serialized_location
13
- serialized[location_type_key] = error.location.location_type if error.location.respond_to? :location_type
14
- end
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
- private
19
+ private
19
20
 
20
- def location_type_key
21
- camelize? ? :locationType : :location_type
22
- end
21
+ def location_type_key
22
+ camelize? ? :locationType : :location_type
23
+ end
23
24
 
24
- def camelize?
25
- @camelize.nil? ? @config.options.camelize : @camelize
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 Plugins::Reason
3
- class << self
4
- attr_writer :config
5
- attr_accessor :camelize
1
+ module Errapi::Plugins
2
+ class Reason < Base
3
+ plugin_name :reason
6
4
 
7
- def serialize_error error, serialized
8
- serialized[:reason] = serialized_reason error
9
- end
5
+ attr_writer :config
6
+ attr_accessor :camelize
10
7
 
11
- private
8
+ def serialize_error error, serialized
9
+ serialized[:reason] = serialized_reason error
10
+ end
11
+
12
+ private
12
13
 
13
- def serialized_reason error
14
- camelize? ? Utils.camelize(error.reason.to_s).to_sym : error.reason
15
- end
14
+ def serialized_reason error
15
+ camelize? ? Utils.camelize(error.reason.to_s).to_sym : error.reason
16
+ end
16
17
 
17
- def camelize?
18
- @camelize.nil? ? @config.options.camelize : @camelize
19
- end
18
+ def camelize?
19
+ @camelize.nil? ? @config.options.camelize : @camelize
20
20
  end
21
21
  end
22
22
  end
@@ -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 Factory
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
- self.class.const_get('Implementation').new options
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
@@ -2,6 +2,10 @@ require File.join(File.dirname(__FILE__), 'clusivity.rb')
2
2
 
3
3
  module Errapi::Validations
4
4
  class Exclusion < Base
5
+ class Factory < ValidationFactory
6
+ build Exclusion
7
+ end
8
+
5
9
  include Clusivity
6
10
 
7
11
  def initialize options = {}
@@ -1,5 +1,8 @@
1
1
  module Errapi::Validations
2
2
  class Format < Base
3
+ class Factory < ValidationFactory
4
+ build Format
5
+ end
3
6
 
4
7
  def initialize options = {}
5
8
  unless key = exactly_one_option?(OPTIONS, options)
@@ -2,6 +2,10 @@ require File.join(File.dirname(__FILE__), 'clusivity.rb')
2
2
 
3
3
  module Errapi::Validations
4
4
  class Inclusion < Base
5
+ class Factory < ValidationFactory
6
+ build Inclusion
7
+ end
8
+
5
9
  include Clusivity
6
10
 
7
11
  def initialize options = {}
@@ -1,5 +1,9 @@
1
1
  module Errapi::Validations
2
2
  class Length < Base
3
+ class Factory < ValidationFactory
4
+ build Length
5
+ end
6
+
3
7
  CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze
4
8
  REASONS = { is: :wrong_length, minimum: :too_short, maximum: :too_long }.freeze
5
9
 
@@ -1,38 +1,39 @@
1
1
  module Errapi::Validations
2
- class Presence < Factory
3
- class Implementation < Base
2
+ class Presence < Base
3
+ class Factory < ValidationFactory
4
+ build Presence
5
+ end
4
6
 
5
- def validate value, context, options = {}
6
- if reason = check(value, options.fetch(:value_set, true))
7
- context.add_error reason: reason
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
- private
13
+ private
12
14
 
13
- BLANK_REGEXP = /\A[[:space:]]*\z/
15
+ BLANK_REGEXP = /\A[[:space:]]*\z/
14
16
 
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
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
- 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
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
@@ -1,5 +1,8 @@
1
1
  module Errapi::Validations
2
2
  class Trim < Base
3
+ class Factory < ValidationFactory
4
+ build Trim
5
+ end
3
6
 
4
7
  def validate value, context, options = {}
5
8
  if value.kind_of?(String) && /(?:\A\s|\s\Z)/.match(value)
@@ -1,5 +1,8 @@
1
1
  module Errapi::Validations
2
2
  class Type < Base
3
+ class Factory < ValidationFactory
4
+ build Type
5
+ end
3
6
 
4
7
  def initialize options = {}
5
8
  unless key = exactly_one_option?(OPTIONS, options)
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.2
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-26 00:00:00.000000000 Z
11
+ date: 2015-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n