veritas 0.0.6 → 0.0.7

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