errapi 0.1.2 → 0.1.3

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
  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