veritas 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.travis.yml +10 -4
  2. data/Gemfile +1 -1
  3. data/TODO +10 -0
  4. data/config/flay.yml +1 -1
  5. data/config/flog.yml +1 -1
  6. data/config/roodi.yml +2 -2
  7. data/config/site.reek +2 -1
  8. data/lib/veritas.rb +2 -2
  9. data/lib/veritas/algebra/join.rb +13 -91
  10. data/lib/veritas/algebra/product.rb +4 -1
  11. data/lib/veritas/attribute.rb +1 -1
  12. data/lib/veritas/function/connective/negation.rb +13 -1
  13. data/lib/veritas/function/numeric/absolute.rb +5 -19
  14. data/lib/veritas/function/numeric/unary.rb +3 -0
  15. data/lib/veritas/function/numeric/unary_minus.rb +5 -19
  16. data/lib/veritas/function/numeric/unary_plus.rb +5 -21
  17. data/lib/veritas/function/proposition.rb +3 -28
  18. data/lib/veritas/function/string/length.rb +0 -1
  19. data/lib/veritas/function/unary.rb +47 -0
  20. data/lib/veritas/relation.rb +16 -2
  21. data/lib/veritas/relation/header.rb +48 -41
  22. data/lib/veritas/relation/operation/order/direction.rb +13 -1
  23. data/lib/veritas/relation/operation/order/direction_set.rb +9 -198
  24. data/lib/veritas/relation/operation/reverse.rb +0 -2
  25. data/lib/veritas/support/comparator.rb +1 -1
  26. data/lib/veritas/support/evaluator.rb +3 -0
  27. data/lib/veritas/support/immutable.rb +33 -8
  28. data/lib/veritas/tuple.rb +8 -6
  29. data/lib/veritas/version.rb +1 -1
  30. data/spec/integration/veritas/algebra/projection_spec.rb +1 -1
  31. data/spec/integration/veritas/relation/efficient_enumerable_spec.rb +40 -15
  32. data/spec/rcov.opts +1 -0
  33. data/spec/shared/hash_method_behavior.rb +10 -5
  34. data/spec/spec_helper.rb +1 -1
  35. data/spec/unit/veritas/algebra/extension/class_methods/new_spec.rb +1 -1
  36. data/spec/unit/veritas/algebra/join/class_methods/new_spec.rb +1 -1
  37. data/spec/unit/veritas/algebra/join/each_spec.rb +36 -9
  38. data/spec/unit/veritas/aliasable/inheritable_alias_spec.rb +1 -1
  39. data/spec/unit/veritas/comparator/compare_spec.rb +4 -1
  40. data/spec/unit/veritas/evaluator/context/method_missing_spec.rb +7 -1
  41. data/spec/unit/veritas/function/connective/negation/class_methods/operation_spec.rb +11 -0
  42. data/spec/unit/veritas/function/numeric/absolute/class_methods/operation_spec.rb +11 -0
  43. data/spec/unit/veritas/function/numeric/unary_minus/class_methods/operation_spec.rb +11 -0
  44. data/spec/unit/veritas/function/numeric/unary_plus/class_methods/operation_spec.rb +11 -0
  45. data/spec/unit/veritas/function/unary/callable/call_spec.rb +23 -0
  46. data/spec/unit/veritas/function/unary/callable/included_spec.rb +23 -0
  47. data/spec/unit/veritas/function/unary/inspect_spec.rb +34 -0
  48. data/spec/unit/veritas/immutable/fixtures/classes.rb +3 -3
  49. data/spec/unit/veritas/immutable/module_methods/memoize_spec.rb +20 -10
  50. data/spec/unit/veritas/relation/class_methods/coerce_spec.rb +23 -0
  51. data/spec/unit/veritas/relation/each_spec.rb +1 -1
  52. data/spec/unit/veritas/relation/equal_value_spec.rb +12 -0
  53. data/spec/unit/veritas/relation/header/call_spec.rb +23 -0
  54. data/spec/unit/veritas/relation/header/class_methods/coerce_spec.rb +1 -1
  55. data/spec/unit/veritas/relation/header/class_methods/new_spec.rb +2 -2
  56. data/spec/unit/veritas/relation/header/each_spec.rb +1 -1
  57. data/spec/unit/veritas/relation/header/empty_spec.rb +5 -4
  58. data/spec/unit/veritas/relation/header/intersect_spec.rb +18 -4
  59. data/spec/unit/veritas/relation/operation/binary/class_methods/new_spec.rb +25 -25
  60. data/spec/unit/veritas/relation/operation/order/direction/name_spec.rb +13 -0
  61. data/spec/unit/veritas/relation/operation/order/direction_set/class_methods/new_spec.rb +1 -1
  62. data/spec/unit/veritas/relation/operation/order/direction_set/equal_value_spec.rb +13 -0
  63. data/spec/unit/veritas/tuple/call_spec.rb +25 -0
  64. data/spec/unit/veritas/tuple/class_methods/coerce_spec.rb +1 -1
  65. data/tasks/metrics/ci.rake +2 -2
  66. data/tasks/metrics/flay.rake +1 -1
  67. data/tasks/metrics/flog.rake +5 -3
  68. data/tasks/metrics/heckle.rake +18 -11
  69. data/tasks/metrics/reek.rake +1 -1
  70. data/tasks/spec.rake +23 -14
  71. data/veritas.gemspec +14 -8
  72. metadata +31 -25
  73. data/spec/unit/veritas/relation/header/element_reference_spec.rb +0 -21
  74. data/spec/unit/veritas/relation/operation/order/direction_set/each_spec.rb +0 -32
  75. data/spec/unit/veritas/relation/operation/order/direction_set/empty_spec.rb +0 -21
  76. data/spec/unit/veritas/relation/operation/order/direction_set/union_spec.rb +0 -18
  77. data/spec/unit/veritas/tuple/element_reference_spec.rb +0 -22
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Function::Numeric::UnaryPlus, '.operation' do
6
+ subject { object.operation }
7
+
8
+ let(:object) { described_class }
9
+
10
+ it { should equal(:+@) }
11
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Function::Unary::Callable, '#call' do
6
+ subject { object.call(value) }
7
+
8
+ let(:object) { mock('object', :operation => :op).extend(self.class.described_type) }
9
+ let(:value) { mock('value', :send => response) }
10
+ let(:response) { mock('response') }
11
+
12
+ it { should equal(response) }
13
+
14
+ it 'uses the operation from the object' do
15
+ object.should_receive(:operation)
16
+ subject
17
+ end
18
+
19
+ it 'delegates the operation to the value' do
20
+ value.should_receive(:send).with(:op)
21
+ subject
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Function::Unary::Callable, '#included' do
6
+ subject { object.included(descendant) }
7
+
8
+ let(:object) { Class.new(superklass).extend(self.class.described_type) }
9
+ let(:superklass) { Class.new }
10
+ let(:descendant) { mock('descendant') }
11
+
12
+ it { should equal(object) }
13
+
14
+ it 'delegates to the superclass #included method' do
15
+ superklass.should_receive(:included).with(descendant)
16
+ subject
17
+ end
18
+
19
+ it 'extends the descendant with Callable' do
20
+ descendant.should_receive(:extend).with(self.class.described_type)
21
+ subject
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Function::Unary, '#inspect' do
6
+ subject { object.inspect }
7
+
8
+ let(:described_class) { Class.new { include Function::Unary } }
9
+ let(:object) { described_class.new(1) }
10
+
11
+ context 'when the operation ends in "@"' do
12
+ before do
13
+ described_class.class_eval do
14
+ def self.operation
15
+ :+@
16
+ end
17
+ end
18
+ end
19
+
20
+ it { should == '+(1)' }
21
+ end
22
+
23
+ context 'when the operation includes a downcased string' do
24
+ before do
25
+ described_class.class_eval do
26
+ def self.operation
27
+ :op
28
+ end
29
+ end
30
+ end
31
+
32
+ it { should == 'OP(1)' }
33
+ end
34
+ end
@@ -9,19 +9,19 @@ module ImmutableSpecs
9
9
  end
10
10
 
11
11
  def public_method
12
- 'public_method'
12
+ caller
13
13
  end
14
14
 
15
15
  protected
16
16
 
17
17
  def protected_method
18
- 'protected_method'
18
+ caller
19
19
  end
20
20
 
21
21
  private
22
22
 
23
23
  def private_method
24
- 'private_method'
24
+ caller
25
25
  end
26
26
 
27
27
  end # class Object
@@ -12,30 +12,40 @@ shared_examples_for 'memoizes method' do
12
12
 
13
13
  it 'creates a method that returns a frozen value' do
14
14
  subject
15
- instance = object.new
16
- instance.send(method).should be_frozen
15
+ object.new.send(method).should be_frozen
17
16
  end
18
17
 
19
18
  specification = proc do
20
- object.send(:define_method, method) do
21
- caller
22
- end
23
-
24
19
  subject
25
-
26
20
  file, line = object.new.send(method).first.split(':')[0, 2]
27
-
28
21
  File.expand_path(file).should eql(File.expand_path('../../../../../../lib/veritas/support/immutable.rb', __FILE__))
29
- line.to_i.should eql(185)
22
+ line.to_i.should eql(210)
30
23
  end
31
24
 
32
25
  it 'sets the file and line number properly' do
33
- if RUBY_PLATFORM[/java/]
26
+ if RUBY_PLATFORM.include?('java')
34
27
  pending('Kernel#caller returns the incorrect line number in JRuby', &specification)
35
28
  else
36
29
  instance_eval(&specification)
37
30
  end
38
31
  end
32
+
33
+ context 'when the initializer calls the memoized method' do
34
+ before do
35
+ method = self.method
36
+ object.send(:define_method, :initialize) { send(method) }
37
+ end
38
+
39
+ it 'allows the memoized method to be called within the initializer' do
40
+ subject
41
+ expect { object.new }.to_not raise_error(NoMethodError)
42
+ end
43
+
44
+ it 'memoizes the methdod inside the initializer' do
45
+ subject
46
+ object.new.memoized(method).should_not be_nil
47
+ end
48
+ end
39
49
  end
40
50
 
41
51
  describe Immutable::ModuleMethods, '#memoize' do
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Relation, '.coerce' do
6
+ subject { object.coerce(header, argument) }
7
+
8
+ let(:header) { [ [ :id, Integer ] ] }
9
+ let(:object) { described_class }
10
+ let(:relation) { Relation.new(header, [ [ 1 ] ]) }
11
+
12
+ context 'when the argument is a Relation' do
13
+ let(:argument) { relation }
14
+
15
+ it { should equal(relation) }
16
+ end
17
+
18
+ context 'when the argument is an Array' do
19
+ let(:argument) { [ [ 1 ] ] }
20
+
21
+ it { should eql(relation) }
22
+ end
23
+ end
@@ -28,7 +28,7 @@ describe Relation do
28
28
 
29
29
  let(:header) { [ [ :id, Integer ] ] }
30
30
  let(:body) { [ [ 1 ] ].each }
31
- let(:object) { Relation }
31
+ let(:object) { described_class }
32
32
 
33
33
  before do
34
34
  subject.should be_instance_of(object)
@@ -103,4 +103,16 @@ describe Relation, '#==' do
103
103
  should eql(other == object)
104
104
  end
105
105
  end
106
+
107
+ context 'with a different object having a superset of the headers' do
108
+ let(:other_header) { [ [ :id, Integer ], [ :name, String ] ] }
109
+ let(:other_body) { [ [ 1, 'Dan Kubb' ] ].each }
110
+ let(:other) { described_class.new(other_header, other_body) }
111
+
112
+ it { should be(false) }
113
+
114
+ it 'is symmetric' do
115
+ should eql(other == object)
116
+ end
117
+ end
106
118
  end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ [ :call, :[] ].each do |method|
6
+ describe Relation::Header, "##{method}" do
7
+ subject { object.send(method, name) }
8
+
9
+ let(:object) { described_class.new([ [ :id, Integer ] ]) }
10
+
11
+ context 'with a known attribute name' do
12
+ let(:name) { :id }
13
+
14
+ it { should == [ :id, Integer ] }
15
+ end
16
+
17
+ context 'with an unknown attribute name' do
18
+ let(:name) { :name }
19
+
20
+ it { should be_nil }
21
+ end
22
+ end
23
+ end
@@ -22,7 +22,7 @@ describe Relation::Header, '.coerce' do
22
22
  end
23
23
 
24
24
  context 'when the argument is not a Header and does not respond to #to_ary' do
25
- let(:argument) { { :id => Integer } }
25
+ let(:argument) { Object.new }
26
26
 
27
27
  specify { expect { subject }.to raise_error(NoMethodError) }
28
28
  end
@@ -26,11 +26,11 @@ describe Relation::Header, '.new' do
26
26
  context 'with an argument that responds to #to_ary and contain duplicates' do
27
27
  let(:argument) { [ [ :id ], [ :id ], [ :name ], [ :name ], [ :age ] ] }
28
28
 
29
- specify { expect { subject }.to raise_error(DuplicateAttributeError, 'duplicate attributes: id, name') }
29
+ specify { expect { subject }.to raise_error(DuplicateNameError, 'duplicate names: id, name') }
30
30
  end
31
31
 
32
32
  context 'with an argument that does not respond to #to_ary' do
33
- let(:argument) { { :id => Integer } }
33
+ let(:argument) { Object.new }
34
34
 
35
35
  specify { expect { subject }.to raise_error(NoMethodError) }
36
36
  end
@@ -21,7 +21,7 @@ end
21
21
  describe Relation::Header do
22
22
  subject { object.new }
23
23
 
24
- let(:object) { Relation::Header }
24
+ let(:object) { described_class }
25
25
 
26
26
  it { should be_kind_of(Enumerable) }
27
27
 
@@ -5,15 +5,16 @@ require 'spec_helper'
5
5
  describe Relation::Header, '#empty?' do
6
6
  subject { object.empty? }
7
7
 
8
+ let(:object) { described_class.new(entries) }
8
9
 
9
- context 'with attributes' do
10
- let(:object) { described_class.new([ [ :id, Integer ] ]) }
10
+ context 'with entries' do
11
+ let(:entries) { [ [ :id, Integer ] ] }
11
12
 
12
13
  it { should be(false) }
13
14
  end
14
15
 
15
- context 'without attributes' do
16
- let(:object) { described_class.new }
16
+ context 'without entries' do
17
+ let(:entries) { [] }
17
18
 
18
19
  it { should be(true) }
19
20
  end
@@ -6,11 +6,25 @@ require 'spec_helper'
6
6
  describe Relation::Header, "##{method}" do
7
7
  subject { object.send(method, other) }
8
8
 
9
- let(:other) { described_class.new([ [ :name, String ] ]) }
10
- let(:object) { described_class.new([ [ :id, Integer ] ]) }
9
+ let(:other) { described_class.new(attributes) }
10
+ let(:object) { described_class.new(other_attributes) }
11
11
 
12
- it { should be_instance_of(described_class) }
12
+ context 'when the attributes overlap' do
13
+ let(:attributes) { [ [ :name, String ] ] }
14
+ let(:other_attributes) { [ [ :name, String ] ] }
13
15
 
14
- it { should be_empty }
16
+ it { should be_instance_of(described_class) }
17
+
18
+ it { should == [ [ :name, String ] ] }
19
+ end
20
+
21
+ context 'when the attributes do not overlap' do
22
+ let(:attributes) { [ [ :name, String ] ] }
23
+ let(:other_attributes) { [ [ :id, Integer ] ] }
24
+
25
+ it { should be_instance_of(described_class) }
26
+
27
+ it { should be_empty }
28
+ end
15
29
  end
16
30
  end
@@ -3,38 +3,38 @@
3
3
  require 'spec_helper'
4
4
  require File.expand_path('../../fixtures/classes', __FILE__)
5
5
 
6
- context 'Veritas::Relation::Operation::Binary::ClassMethods#new' do
7
- subject { object.new(left, right) }
6
+ context 'Veritas::Relation::Operation::Binary::ClassMethods#new' do
7
+ subject { object.new(left, right) }
8
8
 
9
- let(:original_left) { Relation.new([ [ :id, Integer ] ], [ [ 1 ] ]) }
10
- let(:original_right) { Relation.new([ [ :name, String ] ], [ [ 'Dan Kubb' ] ]) }
11
- let(:object) { BinaryRelationOperationSpecs::Object }
9
+ let(:original_left) { Relation.new([ [ :id, Integer ] ], [ [ 1 ] ]) }
10
+ let(:original_right) { Relation.new([ [ :name, String ] ], [ [ 'Dan Kubb' ] ]) }
11
+ let(:object) { BinaryRelationOperationSpecs::Object }
12
12
 
13
- context 'with left and right ordered' do
14
- let(:left) { original_left.sort_by { |r| r.id } }
15
- let(:right) { original_right.sort_by { |r| r.name } }
13
+ context 'with left and right ordered' do
14
+ let(:left) { original_left.sort_by { |r| r.id } }
15
+ let(:right) { original_right.sort_by { |r| r.name } }
16
16
 
17
- it { should be_instance_of(object) }
18
- end
17
+ it { should be_instance_of(object) }
18
+ end
19
19
 
20
- context 'with left and right unordered' do
21
- let(:left) { original_left }
22
- let(:right) { original_right }
20
+ context 'with left and right unordered' do
21
+ let(:left) { original_left }
22
+ let(:right) { original_right }
23
23
 
24
- it { should be_instance_of(object) }
25
- end
24
+ it { should be_instance_of(object) }
25
+ end
26
26
 
27
- context 'with left ordered, and right unordered' do
28
- let(:left) { original_left.sort_by { |r| r.id } }
29
- let(:right) { original_right }
27
+ context 'with left ordered, and right unordered' do
28
+ let(:left) { original_left.sort_by { |r| r.id } }
29
+ let(:right) { original_right }
30
30
 
31
- specify { expect { subject }.to raise_error(RelationMismatchError, 'both relations must be ordered or neither may be ordered') }
32
- end
31
+ specify { expect { subject }.to raise_error(RelationMismatchError, 'both relations must be ordered or neither may be ordered') }
32
+ end
33
33
 
34
- context 'with right ordered, and left unordered' do
35
- let(:left) { original_left }
36
- let(:right) { original_right.sort_by { |r| r.name } }
34
+ context 'with right ordered, and left unordered' do
35
+ let(:left) { original_left }
36
+ let(:right) { original_right.sort_by { |r| r.name } }
37
37
 
38
- specify { expect { subject }.to raise_error(RelationMismatchError, 'both relations must be ordered or neither may be ordered') }
39
- end
38
+ specify { expect { subject }.to raise_error(RelationMismatchError, 'both relations must be ordered or neither may be ordered') }
39
+ end
40
40
  end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Relation::Operation::Order::Direction, '#name' do
6
+ subject { object.name }
7
+
8
+ let(:described_class) { Class.new(Relation::Operation::Order::Direction) }
9
+ let(:attribute) { Attribute::Integer.new(:id) }
10
+ let(:object) { described_class.new(attribute) }
11
+
12
+ it { should equal(:id) }
13
+ end
@@ -21,7 +21,7 @@ describe Relation::Operation::Order::DirectionSet, '.new' do
21
21
  context 'with an argument that responds to #to_ary and contain duplicates' do
22
22
  let(:argument) { [ id, id, name, name, age ] }
23
23
 
24
- specify { expect { subject }.to raise_error(DuplicateAttributeError, 'duplicate attributes: id, name') }
24
+ specify { expect { subject }.to raise_error(DuplicateNameError, 'duplicate names: id, name') }
25
25
  end
26
26
 
27
27
  context 'with an argument that does not respond to #to_ary' do
@@ -49,6 +49,19 @@ describe Relation::Operation::Order::DirectionSet, '#==' do
49
49
  end
50
50
  end
51
51
 
52
+ context 'with an object having equivalent attributes in a different order' do
53
+ let(:attribute1) { Attribute::Integer.new(:id) }
54
+ let(:attribute2) { Attribute::String.new(:name) }
55
+ let(:object) { described_class.new([ attribute1, attribute2 ]) }
56
+ let(:other) { described_class.new([ attribute2, attribute1 ]) }
57
+
58
+ it { should be(false) }
59
+
60
+ it 'is symmetric' do
61
+ should eql(other == object)
62
+ end
63
+ end
64
+
52
65
  context 'with an equivalent object responding to #to_ary' do
53
66
  let(:other) { attributes }
54
67