Skip to content

Commit

Permalink
Validations now support location.
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Oulevay committed Nov 26, 2014
1 parent 60f207e commit 2de9bf7
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 16 deletions.
41 changes: 38 additions & 3 deletions lib/errapi/validation_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,51 @@ def add_error options = {}, &block
self
end

def with options = {}, &block

original_type = @current_type
original_location = @current_location

@current_type = options[:type] if options[:type]
@current_location = actual_location options

yield

@current_type = original_type
@current_location = original_location
end

def validate value, options = {}
if yield value, self, options
true
else
add_error options[:error]
false
end
end

private

def actual_location options
def actual_location options = {}
if options[:location]
options[:location]
absolute_location options[:location]
elsif options[:relative_location]
@current_location ? "#{@current_location}.#{options[:relative_location]}" : options[:relative_location]
@current_location ? relative_location(@current_location, options[:relative_location]) : absolute_location(options[:relative_location])
else
@current_location
end
end

def absolute_location location
location_to_string location
end

def relative_location base, relative
"#{location_to_string(base)}.#{location_to_string(relative)}"
end

def location_to_string location
location.kind_of?(Hash) && location.key?(:value) ? location[:value].to_s : location.to_s
end
end
end
9 changes: 0 additions & 9 deletions lib/errapi/validation_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ def add_error options = {}, &block
self
end

def validate value, options = {}
if yield value, options
true
else
add_error options[:error]
false
end
end

def error? criteria = {}
return !@errors.empty? if criteria.empty?
@errors.any?{ |err| err.matches? criteria }
Expand Down
27 changes: 23 additions & 4 deletions lib/errapi/validations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,21 @@ def validate value, context, options = {}
config = options.delete(:config) || Errapi.config

@validations.each do |validation|
if options[:each]
values = extract options[:each], value
values.each{ |value| perform_validation value, validation, context, config } if values.kind_of? Array
if validation[:each]

values = extract validation[:each], value
next unless values.kind_of? Array

context_options = {}
context_options[:relative_location] = { type: :property, value: validation[:each] } unless validation[:each].respond_to?(:call)

context.with context_options do
values.each.with_index do |value,i|
context.with relative_location: { type: :array_index, value: i } do
perform_validation value, validation, context, config
end
end
end
else
perform_validation value, validation, context, config
end
Expand All @@ -45,9 +57,16 @@ def validator config, validation
end

def perform_validation value, validation, context, config

target = validation[:target]
validator = validator config, validation
validator.validate extract(target, value), context, validation

context_options = {}
context_options[:relative_location] = target unless target.respond_to?(:call)

context.with context_options do
validator.validate extract(target, value), context, validation
end
end

def extract target, value
Expand Down
3 changes: 3 additions & 0 deletions spec/example_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,8 @@
expect(state.error?).to be(true)
expect(state.error?(message: /cannot be null or empty/)).to be(true)
expect(state.errors).to have(3).items
expect(state.error?(location: 'bar.foo')).to be(true)
expect(state.error?(location: 'qux')).to be(true)
expect(state.error?(location: 'baz.2.a')).to be(true)
end
end

0 comments on commit 2de9bf7

Please sign in to comment.