Commit 9223e1a71cde74120bff69d3d46581f3f2e4c7f8

Authored by Alessandro Palmeira
Committed by Diego Camarinha
1 parent e1ee85a8

Added overlapping ranges validation.

Signed off by: Rafael Manzo <rr.manzo@gmail.com>
app/models/mezuro_range.rb
1 1 require "validators/beginning_uniqueness_validator.rb"
2 2 require "validators/greater_than_beginning_validator.rb"
  3 +require "validators/range_overlapping_validator.rb"
3 4  
4 5 class MezuroRange < KalibroGatekeeperClient::Entities::Range
5 6 include KalibroRecord
... ... @@ -12,6 +13,7 @@ class MezuroRange &lt; KalibroGatekeeperClient::Entities::Range
12 13 validates :end, numericality: true, if: :non_infinite_end?
13 14 validates :end, greater_than_beginning: true
14 15 validates :reading_id, presence: true
  16 + validates_with RangeOverlappingValidator
15 17  
16 18 private
17 19  
... ...
app/models/validators/range_overlapping_validator.rb 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +class RangeOverlappingValidator < ActiveModel::Validator
  2 + def validate(record)
  3 + record.class.ranges_of(record.metric_configuration_id).each do |mezuro_range|
  4 + if overlaps?(mezuro_range,record)
  5 + record.errors[:beginning] << "There's already a #{record.class} within these boundaries! Please, choose another ones."
  6 + break
  7 + end
  8 + end
  9 + end
  10 +
  11 + private
  12 +
  13 + def overlaps?(range1, range2)
  14 + return true if to_float(range1.beginning) >= to_float(range2.beginning) && to_float(range1.beginning) < to_float(range2.end)
  15 + return true if to_float(range1.end) > to_float(range2.beginning) && to_float(range1.end) <= to_float(range2.end)
  16 + return true if to_float(range1.beginning) >= to_float(range2.beginning) && to_float(range1.end) <= to_float(range2.end)
  17 + return true if to_float(range1.beginning) <= to_float(range2.beginning) && to_float(range1.end) >= to_float(range2.end)
  18 + return false
  19 + end
  20 +
  21 + def to_float(value)
  22 + return 1.0/0 if value=="INF"
  23 + return -1.0/0 if value=="-INF"
  24 + return value
  25 + end
  26 +end
... ...
spec/models/mezuro_range_spec.rb
... ... @@ -7,6 +7,7 @@ describe MezuroRange, :type =&gt; :model do
7 7 before :each do
8 8 BeginningUniquenessValidator.any_instance.stubs(:validate_each)
9 9 GreaterThanBeginningValidator.any_instance.stubs(:validate_each)
  10 + RangeOverlappingValidator.any_instance.stubs(:validate)
10 11 end
11 12  
12 13 it { is_expected.to validate_presence_of(:beginning) }
... ... @@ -42,27 +43,41 @@ describe MezuroRange, :type =&gt; :model do
42 43 end
43 44 end
44 45 end
45   - end
46 46  
47   - context 'beginning validations' do
48   - before :each do
49   - GreaterThanBeginningValidator.any_instance.stubs(:validate_each)
50   - end
  47 + context 'beginning validations' do
  48 + before :each do
  49 + GreaterThanBeginningValidator.any_instance.stubs(:validate_each)
  50 + RangeOverlappingValidator.any_instance.stubs(:validate)
  51 + end
51 52  
52   - it 'should validate uniqueness' do
53   - BeginningUniquenessValidator.any_instance.expects(:validate_each).with(subject, :beginning, subject.beginning)
54   - subject.save
  53 + it 'should validate uniqueness' do
  54 + BeginningUniquenessValidator.any_instance.expects(:validate_each).with(subject, :beginning, subject.beginning)
  55 + subject.save
  56 + end
55 57 end
56   - end
57 58  
58   - context 'end validations' do
59   - before :each do
60   - BeginningUniquenessValidator.any_instance.stubs(:validate_each)
  59 + context 'end validations' do
  60 + before :each do
  61 + BeginningUniquenessValidator.any_instance.stubs(:validate_each)
  62 + RangeOverlappingValidator.any_instance.stubs(:validate)
  63 + end
  64 +
  65 + it 'should validate that end is greater than beginning' do
  66 + GreaterThanBeginningValidator.any_instance.expects(:validate_each).with(subject, :end, subject.end)
  67 + subject.save
  68 + end
61 69 end
62 70  
63   - it 'should validate that end is greater than beginning' do
64   - GreaterThanBeginningValidator.any_instance.expects(:validate_each).with(subject, :end, subject.end)
65   - subject.save
  71 + context 'overlapping validations' do
  72 + before :each do
  73 + GreaterThanBeginningValidator.any_instance.stubs(:validate_each)
  74 + BeginningUniquenessValidator.any_instance.stubs(:validate_each)
  75 + end
  76 +
  77 + it 'is expected to validate if this range overlaps the existing ones' do
  78 + RangeOverlappingValidator.any_instance.expects(:validate).with(subject)
  79 + subject.save
  80 + end
66 81 end
67 82 end
68 83 end
69 84 \ No newline at end of file
... ...
spec/models/validators/beginning_uniqueness_validator_spec.rb
... ... @@ -8,6 +8,7 @@ describe BeginningUniquenessValidator, :type =&gt; :model do
8 8 before :each do
9 9 MezuroRange.expects(:ranges_of).with(metric_configuration.id).returns([])
10 10 MezuroRange.expects(:request).returns(42)
  11 + RangeOverlappingValidator.any_instance.stubs(:validate)
11 12 end
12 13  
13 14 subject { FactoryGirl.build(:mezuro_range, metric_configuration_id: metric_configuration.id) }
... ... @@ -22,6 +23,7 @@ describe BeginningUniquenessValidator, :type =&gt; :model do
22 23 before :each do
23 24 @subject = FactoryGirl.build(:mezuro_range, metric_configuration_id: metric_configuration.id)
24 25 MezuroRange.expects(:ranges_of).with(@subject.metric_configuration_id).returns([another_mezuro_range])
  26 + RangeOverlappingValidator.any_instance.stubs(:validate)
25 27 end
26 28  
27 29 it 'should contain errors' do
... ...
spec/models/validators/greater_than_beginning_validator_spec.rb
... ... @@ -5,6 +5,7 @@ describe GreaterThanBeginningValidator, :type =&gt; :model do
5 5 describe 'validate_each' do
6 6 before :each do
7 7 BeginningUniquenessValidator.any_instance.stubs(:validate_each)
  8 + RangeOverlappingValidator.any_instance.stubs(:validate)
8 9 end
9 10 context 'when beginning is INF or end is -INF' do
10 11 subject { FactoryGirl.build(:mezuro_range, end: "-INF") }
... ...
spec/models/validators/range_overlapping_validator_spec.rb 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +require 'rails_helper'
  2 +
  3 +describe RangeOverlappingValidator, :type => :model do
  4 + describe 'methods' do
  5 + describe 'validate' do
  6 + let(:metric_configuration) { FactoryGirl.build(:metric_configuration) }
  7 + let(:range) { FactoryGirl.build(:mezuro_range, beginning: '-INF', end: 0.0, metric_configuration_id: metric_configuration.id) }
  8 +
  9 + before :each do
  10 + BeginningUniquenessValidator.any_instance.stubs(:validate_each)
  11 + GreaterThanBeginningValidator.any_instance.stubs(:validate_each)
  12 + end
  13 +
  14 + context 'not overlapping' do
  15 + let!(:not_overlapping_range) { FactoryGirl.build(:mezuro_range, beginning: 0.0, end: 'INF', metric_configuration_id: metric_configuration.id) }
  16 +
  17 + before :each do
  18 + MezuroRange.expects(:ranges_of).with(metric_configuration.id).returns([not_overlapping_range])
  19 + end
  20 +
  21 + it 'is expected to not return errors' do
  22 + range.save
  23 + expect(range.errors).to be_empty
  24 + end
  25 + end
  26 +
  27 + context 'overlapping' do
  28 + let!(:overlapping_range) { FactoryGirl.build(:mezuro_range, beginning: -2.0, end: -1.0, metric_configuration_id: metric_configuration.id) }
  29 +
  30 + before :each do
  31 + MezuroRange.expects(:ranges_of).with(metric_configuration.id).returns([overlapping_range])
  32 + end
  33 +
  34 + it 'is expected to return errors' do
  35 + range.save
  36 + expect(range.errors[:beginning]).to eq(["There's already a #{range.class} within these boundaries! Please, choose another ones."])
  37 + end
  38 + end
  39 + end
  40 + end
  41 +end
... ...