dm-core 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.autotest +29 -0
  2. data/.document +5 -0
  3. data/.gitignore +27 -0
  4. data/LICENSE +20 -0
  5. data/{README.txt → README.rdoc} +14 -3
  6. data/Rakefile +23 -22
  7. data/VERSION +1 -0
  8. data/dm-core.gemspec +201 -10
  9. data/lib/dm-core.rb +32 -23
  10. data/lib/dm-core/adapters.rb +0 -1
  11. data/lib/dm-core/adapters/data_objects_adapter.rb +230 -151
  12. data/lib/dm-core/adapters/mysql_adapter.rb +7 -8
  13. data/lib/dm-core/adapters/oracle_adapter.rb +39 -59
  14. data/lib/dm-core/adapters/postgres_adapter.rb +0 -1
  15. data/lib/dm-core/adapters/sqlite3_adapter.rb +5 -0
  16. data/lib/dm-core/adapters/sqlserver_adapter.rb +114 -0
  17. data/lib/dm-core/adapters/yaml_adapter.rb +0 -5
  18. data/lib/dm-core/associations/many_to_many.rb +118 -56
  19. data/lib/dm-core/associations/many_to_one.rb +48 -21
  20. data/lib/dm-core/associations/one_to_many.rb +8 -30
  21. data/lib/dm-core/associations/one_to_one.rb +1 -5
  22. data/lib/dm-core/associations/relationship.rb +89 -97
  23. data/lib/dm-core/collection.rb +299 -184
  24. data/lib/dm-core/core_ext/enumerable.rb +28 -0
  25. data/lib/dm-core/core_ext/kernel.rb +0 -2
  26. data/lib/dm-core/migrations.rb +314 -170
  27. data/lib/dm-core/model.rb +97 -66
  28. data/lib/dm-core/model/descendant_set.rb +1 -1
  29. data/lib/dm-core/model/hook.rb +0 -3
  30. data/lib/dm-core/model/property.rb +7 -10
  31. data/lib/dm-core/model/relationship.rb +79 -26
  32. data/lib/dm-core/model/scope.rb +3 -4
  33. data/lib/dm-core/property.rb +152 -90
  34. data/lib/dm-core/property_set.rb +18 -37
  35. data/lib/dm-core/query.rb +452 -153
  36. data/lib/dm-core/query/conditions/comparison.rb +266 -173
  37. data/lib/dm-core/query/conditions/operation.rb +499 -57
  38. data/lib/dm-core/query/direction.rb +0 -3
  39. data/lib/dm-core/query/operator.rb +0 -4
  40. data/lib/dm-core/query/path.rb +10 -12
  41. data/lib/dm-core/query/sort.rb +4 -10
  42. data/lib/dm-core/repository.rb +10 -6
  43. data/lib/dm-core/resource.rb +343 -148
  44. data/lib/dm-core/spec/adapter_shared_spec.rb +17 -1
  45. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +277 -17
  46. data/lib/dm-core/support/chainable.rb +0 -2
  47. data/lib/dm-core/support/equalizer.rb +27 -3
  48. data/lib/dm-core/transaction.rb +75 -75
  49. data/lib/dm-core/type.rb +19 -5
  50. data/lib/dm-core/types/discriminator.rb +4 -4
  51. data/lib/dm-core/types/object.rb +2 -7
  52. data/lib/dm-core/types/paranoid_boolean.rb +8 -2
  53. data/lib/dm-core/types/paranoid_datetime.rb +8 -2
  54. data/lib/dm-core/version.rb +1 -1
  55. data/script/performance.rb +7 -7
  56. data/script/profile.rb +6 -6
  57. data/spec/lib/collection_helpers.rb +2 -2
  58. data/spec/lib/pending_helpers.rb +22 -3
  59. data/spec/lib/rspec_immediate_feedback_formatter.rb +1 -0
  60. data/spec/public/associations/many_to_many_spec.rb +6 -4
  61. data/spec/public/associations/many_to_one_spec.rb +10 -1
  62. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +39 -0
  63. data/spec/public/associations/one_to_many_spec.rb +4 -3
  64. data/spec/public/associations/one_to_one_spec.rb +19 -1
  65. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +45 -0
  66. data/spec/public/collection_spec.rb +4 -3
  67. data/spec/public/migrations_spec.rb +144 -0
  68. data/spec/public/model/relationship_spec.rb +115 -55
  69. data/spec/public/model_spec.rb +13 -13
  70. data/spec/public/property/object_spec.rb +106 -0
  71. data/spec/public/property_spec.rb +18 -14
  72. data/spec/public/resource_spec.rb +10 -1
  73. data/spec/public/sel_spec.rb +16 -49
  74. data/spec/public/setup_spec.rb +1 -1
  75. data/spec/public/shared/association_collection_shared_spec.rb +6 -14
  76. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  77. data/spec/public/shared/collection_shared_spec.rb +214 -217
  78. data/spec/public/shared/finder_shared_spec.rb +259 -365
  79. data/spec/public/shared/resource_shared_spec.rb +524 -248
  80. data/spec/public/transaction_spec.rb +27 -3
  81. data/spec/public/types/discriminator_spec.rb +1 -1
  82. data/spec/rcov.opts +6 -0
  83. data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +17 -0
  84. data/spec/semipublic/associations/many_to_one_spec.rb +3 -20
  85. data/spec/semipublic/associations_spec.rb +2 -2
  86. data/spec/semipublic/collection_spec.rb +0 -32
  87. data/spec/semipublic/model_spec.rb +96 -0
  88. data/spec/semipublic/property_spec.rb +3 -3
  89. data/spec/semipublic/query/conditions/comparison_spec.rb +1719 -0
  90. data/spec/semipublic/query/conditions/operation_spec.rb +1292 -0
  91. data/spec/semipublic/query_spec.rb +1285 -144
  92. data/spec/semipublic/resource_spec.rb +0 -24
  93. data/spec/semipublic/shared/resource_shared_spec.rb +103 -38
  94. data/spec/spec.opts +1 -1
  95. data/spec/spec_helper.rb +15 -6
  96. data/tasks/ci.rake +1 -0
  97. data/tasks/metrics.rake +37 -0
  98. data/tasks/spec.rake +41 -0
  99. data/tasks/yard.rake +9 -0
  100. data/tasks/yardstick.rake +19 -0
  101. metadata +99 -29
  102. data/CONTRIBUTING +0 -51
  103. data/FAQ +0 -93
  104. data/History.txt +0 -27
  105. data/MIT-LICENSE +0 -22
  106. data/Manifest.txt +0 -121
  107. data/QUICKLINKS +0 -11
  108. data/SPECS +0 -35
  109. data/TODO +0 -1
  110. data/spec/semipublic/query/conditions_spec.rb +0 -528
  111. data/tasks/ci.rb +0 -24
  112. data/tasks/dm.rb +0 -58
  113. data/tasks/doc.rb +0 -17
  114. data/tasks/gemspec.rb +0 -23
  115. data/tasks/hoe.rb +0 -45
  116. data/tasks/install.rb +0 -18
@@ -12,7 +12,10 @@ describe DataMapper::Resource, 'Transactions' do
12
12
  property :description, Text
13
13
  property :admin, Boolean, :accessor => :private
14
14
 
15
- belongs_to :referrer, self, :nullable => true
15
+ belongs_to :parent, self, :required => false
16
+ has n, :children, self, :inverse => :parent
17
+
18
+ belongs_to :referrer, self, :required => false
16
19
  has n, :comments
17
20
 
18
21
  # FIXME: figure out a different approach than stubbing things out
@@ -51,6 +54,12 @@ describe DataMapper::Resource, 'Transactions' do
51
54
  end
52
55
  end
53
56
 
57
+ class ::Default
58
+ include DataMapper::Resource
59
+
60
+ property :name, String, :key => true, :default => 'a default value'
61
+ end
62
+
54
63
  @user_model = Blog::User
55
64
  @author_model = Blog::Author
56
65
  @comment_model = Blog::Comment
@@ -58,7 +67,7 @@ describe DataMapper::Resource, 'Transactions' do
58
67
  @paragraph_model = Blog::Paragraph
59
68
  end
60
69
 
61
- supported_by :postgres, :mysql, :sqlite3, :oracle do
70
+ supported_by :postgres, :mysql, :sqlite3, :oracle, :sqlserver do
62
71
  before :all do
63
72
  user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test')
64
73
 
@@ -84,7 +93,7 @@ describe DataMapper::Resource, 'Transactions' do
84
93
  it_should_behave_like 'A Resource supporting Strategic Eager Loading'
85
94
  end
86
95
 
87
- supported_by :postgres, :mysql, :sqlite3, :oracle do
96
+ supported_by :postgres, :mysql, :sqlite3, :oracle, :sqlserver do
88
97
  describe '#transaction' do
89
98
  before do
90
99
  @user_model.all.destroy!
@@ -121,6 +130,21 @@ describe DataMapper::Resource, 'Transactions' do
121
130
  @user_model.all.should have(0).entries
122
131
  end
123
132
 
133
+ it 'should close the transaction if return is called within the closure' do
134
+ @txn = nil
135
+
136
+ def doit
137
+ @user_model.transaction do
138
+ @txn = Thread.current[:dm_transactions].last
139
+ return
140
+ end
141
+ end
142
+ doit
143
+
144
+ @txn.instance_variable_get(:@state).should == :commit
145
+ @txn = nil
146
+ end
147
+
124
148
  it 'should return the last statement in the transaction block' do
125
149
  @user_model.transaction { 1 }.should == 1
126
150
  end
@@ -7,7 +7,7 @@ describe DataMapper::Types::Discriminator do
7
7
  include DataMapper::Resource
8
8
 
9
9
  property :id, Serial
10
- property :title, String, :nullable => false
10
+ property :title, String, :required => true
11
11
  property :type, Discriminator
12
12
  end
13
13
 
data/spec/rcov.opts ADDED
@@ -0,0 +1,6 @@
1
+ --exclude "spec"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ dir = DataMapper.root / 'lib' / 'dm-core' / 'spec'
4
+
5
+ require dir / 'adapter_shared_spec'
6
+ require dir / 'data_objects_adapter_shared_spec'
7
+
8
+ describe 'Adapter' do
9
+ supported_by :sqlserver do
10
+ describe DataMapper::Adapters::SqlserverAdapter do
11
+
12
+ it_should_behave_like 'An Adapter'
13
+ it_should_behave_like 'A DataObjects Adapter'
14
+
15
+ end
16
+ end
17
+ end
@@ -12,40 +12,23 @@ describe 'Many to One Associations' do
12
12
  has n, :comments
13
13
  end
14
14
 
15
- # This is a special class that needs to be an exact copy of User
16
- class ::Clone
17
- include DataMapper::Resource
18
-
19
- property :name, String, :key => true
20
- property :age, Integer
21
- property :description, Text
22
- end
23
-
24
15
  class ::Comment
25
16
  include DataMapper::Resource
26
17
 
27
- property :id, Serial
28
- property :body, Text
18
+ property :id, Serial
29
19
 
30
20
  belongs_to :user
31
21
  end
32
22
 
33
- class ::Default
34
- include DataMapper::Resource
35
-
36
- property :name, String, :key => true, :default => 'a default value'
37
- end
38
-
39
23
  @user_model = User
40
24
  @comment_model = Comment
41
25
  end
42
26
 
43
27
  supported_by :all do
44
28
  before :all do
45
- comment = @comment_model.create(:body => 'Cool spec', :user => User.create(:name => 'dbussink', :age => 25, :description => 'Test'))
29
+ comment = @comment_model.create(:user => User.create(:name => 'dbussink', :age => 25, :description => 'Test'))
46
30
 
47
- comment = @comment_model.get(*comment.key)
48
- @user = comment.user
31
+ @user = @comment_model.get(*comment.key).user
49
32
  end
50
33
 
51
34
  it_should_behave_like 'A semipublic Resource'
@@ -170,8 +170,8 @@ describe DataMapper::Associations do
170
170
  @relationship.max.should == 1
171
171
  end
172
172
 
173
- it 'should return a Relationship that is not nullable' do
174
- @relationship.nullable?.should be_false
173
+ it 'should return a Relationship that is required' do
174
+ @relationship.required?.should be_true
175
175
  end
176
176
  end
177
177
  end
@@ -74,22 +74,6 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
74
74
  end
75
75
  end
76
76
 
77
- it { @articles.should respond_to(:properties) }
78
-
79
- describe '#properties' do
80
- before :all do
81
- @return = @properties = @articles.properties
82
- end
83
-
84
- it 'should return a PropertySet' do
85
- @return.should be_kind_of(DataMapper::PropertySet)
86
- end
87
-
88
- it 'should be expected properties' do
89
- @properties.to_a.should == @articles_query.fields
90
- end
91
- end
92
-
93
77
  it { @articles.should respond_to(:query) }
94
78
 
95
79
  describe '#query' do
@@ -106,22 +90,6 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
106
90
  end
107
91
  end
108
92
 
109
- it { @articles.should respond_to(:relationships) }
110
-
111
- describe '#relationships' do
112
- before :all do
113
- @return = @relationships = @articles.relationships
114
- end
115
-
116
- it 'should return a Hash' do
117
- @return.should be_kind_of(Hash)
118
- end
119
-
120
- it 'should return expected Hash' do
121
- @return.should equal(@article_model.relationships(@article_repository.name))
122
- end
123
- end
124
-
125
93
  it { @articles.should respond_to(:repository) }
126
94
 
127
95
  describe '#repository' do
@@ -0,0 +1,96 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe DataMapper::Model do
4
+
5
+ it { should respond_to(:append_inclusions) }
6
+
7
+ describe '.append_inclusions' do
8
+ module ::Inclusions
9
+ def new_method
10
+ end
11
+ end
12
+
13
+ describe 'before the model is defined' do
14
+ before :all do
15
+ DataMapper::Model.append_inclusions(Inclusions)
16
+
17
+ class ::User
18
+ include DataMapper::Resource
19
+ property :id, Serial
20
+ end
21
+ end
22
+
23
+ it 'should respond to :new_method' do
24
+ User.new.should respond_to(:new_method)
25
+ end
26
+
27
+ after :all do
28
+ DataMapper::Model.extra_inclusions.delete(Inclusions)
29
+ end
30
+ end
31
+
32
+ describe 'after the model is defined' do
33
+ before :all do
34
+ class ::User
35
+ include DataMapper::Resource
36
+ property :id, Serial
37
+ end
38
+ DataMapper::Model.append_inclusions(Inclusions)
39
+ end
40
+
41
+ it 'should respond to :new_method' do
42
+ User.new.should respond_to(:new_method)
43
+ end
44
+
45
+ after :all do
46
+ DataMapper::Model.extra_inclusions.delete(Inclusions)
47
+ end
48
+ end
49
+ end
50
+
51
+ it { should respond_to(:append_extensions) }
52
+
53
+ describe '.append_extensions' do
54
+ module ::Extensions
55
+ def new_method
56
+ end
57
+ end
58
+
59
+ describe 'before the model is defined' do
60
+ before :all do
61
+ DataMapper::Model.append_extensions(Extensions)
62
+
63
+ class ::User
64
+ include DataMapper::Resource
65
+ property :id, Serial
66
+ end
67
+ end
68
+
69
+ it 'should respond to :new_method' do
70
+ User.should respond_to(:new_method)
71
+ end
72
+
73
+ after :all do
74
+ DataMapper::Model.extra_extensions.delete(Extensions)
75
+ end
76
+ end
77
+
78
+ describe 'after the model is defined' do
79
+ before :all do
80
+ class ::User
81
+ include DataMapper::Resource
82
+ property :id, Serial
83
+ end
84
+ DataMapper::Model.append_extensions(Extensions)
85
+ end
86
+
87
+ it 'should respond to :new_method' do
88
+ User.should respond_to(:new_method)
89
+ end
90
+
91
+ after :all do
92
+ DataMapper::Model.extra_extensions.delete(Extensions)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -455,7 +455,7 @@ describe DataMapper::Property do
455
455
  end
456
456
 
457
457
  it 'does not typecast non-time values' do
458
- pending 'Time#parse is too permissive' do
458
+ pending_if 'Time#parse is too permissive', RUBY_VERSION <= '1.9.1' do
459
459
  @property.typecast('not-time').should eql('not-time')
460
460
  end
461
461
  end
@@ -517,13 +517,13 @@ describe DataMapper::Property do
517
517
  end
518
518
  end
519
519
 
520
- describe 'when provide a nil value when not nullable' do
520
+ describe 'when provide a nil value when required' do
521
521
  it 'should return false' do
522
522
  @model.properties[:id].valid?(nil).should be_false
523
523
  end
524
524
  end
525
525
 
526
- describe 'when provide a nil value when nullable' do
526
+ describe 'when provide a nil value when not required' do
527
527
  it 'should return false' do
528
528
  @model.properties[:alias].valid?(nil).should be_true
529
529
  end
@@ -0,0 +1,1719 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
2
+
3
+ shared_examples_for 'DataMapper::Query::Conditions::AbstractComparison' do
4
+ before :all do
5
+ module ::Blog
6
+ class Article
7
+ include DataMapper::Resource
8
+
9
+ property :id, Serial
10
+ property :title, String, :required => true
11
+
12
+ belongs_to :parent, self, :required => false
13
+ has n, :children, self, :inverse => :parent
14
+ end
15
+ end
16
+
17
+ @model = Blog::Article
18
+ end
19
+
20
+ before do
21
+ class ::OtherComparison < DataMapper::Query::Conditions::AbstractComparison
22
+ slug :other
23
+ end
24
+ end
25
+
26
+ before do
27
+ @relationship = @model.relationships[:parent]
28
+ end
29
+
30
+ it { subject.class.should respond_to(:new) }
31
+
32
+ describe '.new' do
33
+ subject { @comparison.class.new(@property, @value) }
34
+
35
+ it { should be_kind_of(@comparison.class) }
36
+
37
+ it { subject.subject.should equal(@property) }
38
+
39
+ it { subject.value.should == @value }
40
+ end
41
+
42
+ it { subject.class.should respond_to(:slug) }
43
+
44
+ describe '.slug' do
45
+ describe 'with no arguments' do
46
+ subject { @comparison.class.slug }
47
+
48
+ it { should == @slug }
49
+ end
50
+
51
+ describe 'with an argument' do
52
+ subject { @comparison.class.slug(:other) }
53
+
54
+ it { should == :other }
55
+
56
+ # reset the slug
57
+ after { @comparison.class.slug(@slug) }
58
+ end
59
+ end
60
+
61
+ it { should respond_to(:==) }
62
+
63
+ describe '#==' do
64
+ describe 'when the other AbstractComparison is equal' do
65
+ # artifically modify the object so #== will throw an
66
+ # exception if the equal? branch is not followed when heckling
67
+ before { @comparison.meta_class.send(:undef_method, :slug) }
68
+
69
+ subject { @comparison == @comparison }
70
+
71
+ it { should be_true }
72
+ end
73
+
74
+ describe 'when the other AbstractComparison is the same class' do
75
+ subject { @comparison == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value) }
76
+
77
+ it { should be_true }
78
+ end
79
+
80
+ describe 'when the other AbstractComparison is a different class' do
81
+ subject { @comparison == DataMapper::Query::Conditions::Comparison.new(:other, @property, @value) }
82
+
83
+ it { should be_false }
84
+ end
85
+
86
+ describe 'when the other AbstractComparison is the same class, with different property' do
87
+ subject { @comparison == DataMapper::Query::Conditions::Comparison.new(@slug, @other_property, @value) }
88
+
89
+ it { should be_false }
90
+ end
91
+
92
+ describe 'when the other AbstractComparison is the same class, with different value' do
93
+ subject { @comparison == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @other_value) }
94
+
95
+ it { should be_false }
96
+ end
97
+ end
98
+
99
+ it { should respond_to(:eql?) }
100
+
101
+ describe '#eql?' do
102
+ describe 'when the other AbstractComparison is equal' do
103
+ # artifically modify the object so #eql? will throw an
104
+ # exception if the equal? branch is not followed when heckling
105
+ before { @comparison.meta_class.send(:undef_method, :slug) }
106
+
107
+ subject { @comparison.eql?(@comparison) }
108
+
109
+ it { should be_true }
110
+ end
111
+
112
+ describe 'when the other AbstractComparison is the same class' do
113
+ subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)) }
114
+
115
+ it { should be_true }
116
+ end
117
+
118
+ describe 'when the other AbstractComparison is a different class' do
119
+ subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(:other, @property, @value)) }
120
+
121
+ it { should be_false }
122
+ end
123
+
124
+ describe 'when the other AbstractComparison is the same class, with different property' do
125
+ subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(@slug, @other_property, @value)) }
126
+
127
+ it { should be_false }
128
+ end
129
+
130
+ describe 'when the other AbstractComparison is the same class, with different value' do
131
+ subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(@slug, @property, @other_value)) }
132
+
133
+ it { should be_false }
134
+ end
135
+ end
136
+
137
+ it { should respond_to(:hash) }
138
+
139
+ describe '#hash' do
140
+ subject { @comparison.hash }
141
+
142
+ it 'should match the same AbstractComparison with the same property and value' do
143
+ should == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value).hash
144
+ end
145
+
146
+ it 'should not match the same AbstractComparison with different property' do
147
+ should_not == DataMapper::Query::Conditions::Comparison.new(@slug, @other_property, @value).hash
148
+ end
149
+
150
+ it 'should not match the same AbstractComparison with different value' do
151
+ should_not == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @other_value).hash
152
+ end
153
+
154
+ it 'should not match a different AbstractComparison with the same property and value' do
155
+ should_not == @other.hash
156
+ end
157
+
158
+ it 'should not match a different AbstractComparison with different property' do
159
+ should_not == @other.class.new(@other_property, @value).hash
160
+ end
161
+
162
+ it 'should not match a different AbstractComparison with different value' do
163
+ should_not == @other.class.new(@property, @other_value).hash
164
+ end
165
+ end
166
+
167
+ it { should respond_to(:loaded_value) }
168
+
169
+ describe '#loaded_value' do
170
+ subject { @comparison.loaded_value }
171
+
172
+ it { should == @value }
173
+ end
174
+
175
+ it { should respond_to(:parent) }
176
+
177
+ describe '#parent' do
178
+ subject { @comparison.parent }
179
+
180
+ describe 'should be nil by default' do
181
+ it { should be_nil }
182
+ end
183
+
184
+ describe 'should relate to parent operation' do
185
+ before do
186
+ @operation = DataMapper::Query::Conditions::Operation.new(:and)
187
+ @comparison.parent = @operation
188
+ end
189
+
190
+ it { should be_equal(@operation) }
191
+ end
192
+ end
193
+
194
+ it { should respond_to(:parent=) }
195
+
196
+ describe '#parent=' do
197
+ before do
198
+ @operation = DataMapper::Query::Conditions::Operation.new(:and)
199
+ end
200
+
201
+ subject { @comparison.parent = @operation }
202
+
203
+ it { should equal(@operation) }
204
+
205
+ it 'should change the parent' do
206
+ method(:subject).should change(@comparison, :parent).
207
+ from(nil).
208
+ to(@operation)
209
+ end
210
+ end
211
+
212
+ it { should respond_to(:property?) }
213
+
214
+ describe '#property?' do
215
+ subject { @comparison.property? }
216
+
217
+ it { should be_true }
218
+ end
219
+
220
+ it { should respond_to(:slug) }
221
+
222
+ describe '#slug' do
223
+ subject { @comparison.slug }
224
+
225
+ it { should == @slug }
226
+ end
227
+
228
+ it { should respond_to(:subject) }
229
+
230
+ describe '#subject' do
231
+ subject { @comparison.subject }
232
+
233
+ it { should be_equal(@property) }
234
+ end
235
+
236
+ it { should respond_to(:valid?) }
237
+
238
+ describe '#valid?' do
239
+ subject { @comparison.valid? }
240
+
241
+ describe 'when the value is valid for the subject' do
242
+ it { should be_true }
243
+ end
244
+
245
+ describe 'when the value is not valid for the subject' do
246
+ before do
247
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, nil)
248
+ end
249
+
250
+ it { should be_false }
251
+ end
252
+ end
253
+
254
+ it { should respond_to(:value) }
255
+
256
+ describe '#value' do
257
+ subject { @comparison.value }
258
+
259
+ it { should == @value }
260
+ end
261
+ end
262
+
263
+ describe DataMapper::Query::Conditions::Comparison do
264
+ before :all do
265
+ module ::Blog
266
+ class Article
267
+ include DataMapper::Resource
268
+
269
+ property :id, Serial
270
+ property :title, String, :required => true
271
+ end
272
+ end
273
+
274
+ @model = Blog::Article
275
+ end
276
+
277
+ before :all do
278
+ @property = @model.properties[:id]
279
+ end
280
+
281
+ it { DataMapper::Query::Conditions::Comparison.should respond_to(:new) }
282
+
283
+ describe '.new' do
284
+ {
285
+ :eql => DataMapper::Query::Conditions::EqualToComparison,
286
+ :in => DataMapper::Query::Conditions::InclusionComparison,
287
+ :regexp => DataMapper::Query::Conditions::RegexpComparison,
288
+ :like => DataMapper::Query::Conditions::LikeComparison,
289
+ :gt => DataMapper::Query::Conditions::GreaterThanComparison,
290
+ :lt => DataMapper::Query::Conditions::LessThanComparison,
291
+ :gte => DataMapper::Query::Conditions::GreaterThanOrEqualToComparison,
292
+ :lte => DataMapper::Query::Conditions::LessThanOrEqualToComparison,
293
+ }.each do |slug, klass|
294
+ describe "with a slug #{slug.inspect}" do
295
+ subject { DataMapper::Query::Conditions::Comparison.new(slug, @property, @value) }
296
+
297
+ it { should be_kind_of(klass) }
298
+ end
299
+ end
300
+
301
+ describe 'with an invalid slug' do
302
+ subject { DataMapper::Query::Conditions::Comparison.new(:invalid, @property, @value) }
303
+
304
+ it { method(:subject).should raise_error(ArgumentError, 'No Comparison class for :invalid has been defined') }
305
+ end
306
+ end
307
+ end
308
+
309
+ describe DataMapper::Query::Conditions::EqualToComparison do
310
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
311
+
312
+ before do
313
+ @property = @model.properties[:id]
314
+ @other_property = @model.properties[:title]
315
+ @value = 1
316
+ @other_value = 2
317
+ @slug = :eql
318
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
319
+ @other = OtherComparison.new(@property, @value)
320
+ end
321
+
322
+ subject { @comparison }
323
+
324
+ it { should respond_to(:foreign_key_mapping) }
325
+
326
+ describe '#foreign_key_mapping' do
327
+ supported_by :all do
328
+ before do
329
+ @parent = @model.create(:title => 'Parent')
330
+ @child = @parent.children.create(:title => 'Child')
331
+
332
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent)
333
+ end
334
+
335
+ it 'should return criteria that matches the record' do
336
+ @model.all(:conditions => @comparison.foreign_key_mapping).should == [ @child ]
337
+ end
338
+ end
339
+ end
340
+
341
+ it { should respond_to(:inspect) }
342
+
343
+ describe '#inspect' do
344
+ subject { @comparison.inspect }
345
+
346
+ it { should == '#<DataMapper::Query::Conditions::EqualToComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:id> @dumped_value=1 @loaded_value=1>' }
347
+ end
348
+
349
+ it { should respond_to(:matches?) }
350
+
351
+ describe '#matches?' do
352
+ supported_by :all do
353
+ describe 'with a Property subject' do
354
+ describe 'with an Integer value' do
355
+ describe 'with a matching Hash' do
356
+ subject { @comparison.matches?(@property.field => 1) }
357
+
358
+ it { should be_true }
359
+ end
360
+
361
+ describe 'with a not matching Hash' do
362
+ subject { @comparison.matches?(@property.field => 2) }
363
+
364
+ it { should be_false }
365
+ end
366
+
367
+ describe 'with a matching Resource' do
368
+ subject { @comparison.matches?(@model.new(@property => 1)) }
369
+
370
+ it { should be_true }
371
+ end
372
+
373
+ describe 'with a not matching Resource' do
374
+ subject { @comparison.matches?(@model.new(@property => 2)) }
375
+
376
+ it { should be_false }
377
+ end
378
+ end
379
+
380
+ describe 'with a nil value' do
381
+ before do
382
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, nil)
383
+ end
384
+
385
+ describe 'with a matching Hash' do
386
+ subject { @comparison.matches?(@property.field => nil) }
387
+
388
+ it { should be_true }
389
+ end
390
+
391
+ describe 'with a not matching Hash' do
392
+ subject { @comparison.matches?(@property.field => 1) }
393
+
394
+ it { should be_false }
395
+ end
396
+
397
+ describe 'with a matching Resource' do
398
+ subject { @comparison.matches?(@model.new(@property => nil)) }
399
+
400
+ it { should be_true }
401
+ end
402
+
403
+ describe 'with a not matching Resource' do
404
+ subject { @comparison.matches?(@model.new(@property => 1)) }
405
+
406
+ it { should be_false }
407
+ end
408
+ end
409
+ end
410
+
411
+ describe 'with a Relationship subject' do
412
+ describe 'with a Relationship subject and a nil value' do
413
+ before do
414
+ @parent = @model.create(:title => 'Parent')
415
+ @child = @parent.children.create(:title => 'Child')
416
+
417
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, nil)
418
+ end
419
+
420
+ describe 'with a matching Hash' do
421
+ subject { @comparison.matches?({ @relationship.field => nil }) }
422
+
423
+ it { should be_true }
424
+ end
425
+
426
+ describe 'with a not matching Hash' do
427
+ subject { @comparison.matches?({ @relationship.field => {} }) }
428
+
429
+ it { pending { should be_false } }
430
+ end
431
+
432
+ describe 'with a matching Resource' do
433
+ subject { @comparison.matches?(@parent) }
434
+
435
+ it { should be_true }
436
+ end
437
+
438
+ describe 'with a not matching Resource' do
439
+ subject { @comparison.matches?(@child) }
440
+
441
+ it { should be_false }
442
+ end
443
+ end
444
+
445
+ describe 'with a Relationship subject and a Hash value' do
446
+ before do
447
+ @parent = @model.create(:title => 'Parent')
448
+ @child = @parent.children.create(:title => 'Child')
449
+
450
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent.attributes.except(:id))
451
+ end
452
+
453
+ describe 'with a matching Hash' do
454
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
455
+
456
+ it { should be_true }
457
+ end
458
+
459
+ describe 'with a not matching Hash' do
460
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
461
+
462
+ it { pending { should be_false } }
463
+ end
464
+
465
+ describe 'with a matching Resource' do
466
+ subject { @comparison.matches?(@child) }
467
+
468
+ it { pending { should be_true } }
469
+ end
470
+
471
+ describe 'with a not matching Resource' do
472
+ subject { @comparison.matches?(@parent) }
473
+
474
+ it { pending { should be_false } }
475
+ end
476
+ end
477
+
478
+ describe 'with a Relationship subject and new Resource value' do
479
+ before do
480
+ @parent = @model.create(:title => 'Parent')
481
+ @child = @parent.children.create(:title => 'Child')
482
+
483
+ new_resource = @model.new(@parent.attributes.except(:id))
484
+
485
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, new_resource)
486
+ end
487
+
488
+ describe 'with a matching Hash' do
489
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
490
+
491
+ it { should be_true }
492
+ end
493
+
494
+ describe 'with a not matching Hash' do
495
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
496
+
497
+ it { pending { should be_false } }
498
+ end
499
+
500
+ describe 'with a matching Resource' do
501
+ subject { @comparison.matches?(@child) }
502
+
503
+ it { pending { should be_true } }
504
+ end
505
+
506
+ describe 'with a not matching Resource' do
507
+ subject { @comparison.matches?(@parent) }
508
+
509
+ it { pending { should be_false } }
510
+ end
511
+ end
512
+
513
+ describe 'with a Relationship subject and saved Resource value' do
514
+ before do
515
+ @parent = @model.create(:title => 'Parent')
516
+ @child = @parent.children.create(:title => 'Child')
517
+
518
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent)
519
+ end
520
+
521
+ describe 'with a matching Hash' do
522
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
523
+
524
+ it { pending { should be_true } }
525
+ end
526
+
527
+ describe 'with a not matching Hash' do
528
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
529
+
530
+ it { should be_false }
531
+ end
532
+
533
+ describe 'with a matching Resource' do
534
+ subject { @comparison.matches?(@child) }
535
+
536
+ it { should be_true }
537
+ end
538
+
539
+ describe 'with a not matching Resource' do
540
+ subject { @comparison.matches?(@parent) }
541
+
542
+ it { should be_false }
543
+ end
544
+ end
545
+ end
546
+ end
547
+ end
548
+
549
+ it { should respond_to(:relationship?) }
550
+
551
+ describe '#relationship?' do
552
+ subject { @comparison.relationship? }
553
+
554
+ it { should be_false }
555
+ end
556
+
557
+ it { should respond_to(:to_s) }
558
+
559
+ describe '#to_s' do
560
+ subject { @comparison.to_s }
561
+
562
+ it { should == 'id = 1' }
563
+ end
564
+
565
+ it { should respond_to(:value) }
566
+
567
+ describe '#value' do
568
+ supported_by :all do
569
+ subject { @comparison.value }
570
+
571
+ describe 'with a Property subject' do
572
+ describe 'with an Integer value' do
573
+ it { should == @value }
574
+ end
575
+
576
+ describe 'with a nil value' do
577
+ before do
578
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, nil)
579
+ end
580
+
581
+ it { should be_nil }
582
+ end
583
+ end
584
+
585
+ describe 'with a Relationship subject' do
586
+ before :all do
587
+ @parent = @model.create(:title => 'Parent')
588
+ @child = @parent.children.create(:title => 'Child')
589
+ end
590
+
591
+ describe 'with an Hash value' do
592
+ before do
593
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, :id => 1)
594
+ end
595
+
596
+ it { should == @model.new(:id => 1) }
597
+ end
598
+
599
+ describe 'with a Resource value' do
600
+ before do
601
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent)
602
+ end
603
+
604
+ it { should == @parent }
605
+ end
606
+ end
607
+ end
608
+ end
609
+ end
610
+
611
+ describe DataMapper::Query::Conditions::InclusionComparison do
612
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
613
+
614
+ before do
615
+ @property = @model.properties[:id]
616
+ @other_property = @model.properties[:title]
617
+ @value = [ 1 ]
618
+ @other_value = [ 2 ]
619
+ @slug = :in
620
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
621
+ @other = OtherComparison.new(@property, @value)
622
+ end
623
+
624
+ subject { @comparison }
625
+
626
+ it { should respond_to(:foreign_key_mapping) }
627
+
628
+ describe '#foreign_key_mapping' do
629
+ supported_by :all do
630
+ before do
631
+ @parent = @model.create(:title => 'Parent')
632
+ @child = @parent.children.create(:title => 'Child')
633
+
634
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @model.all)
635
+ end
636
+
637
+ it 'should return criteria that matches the record' do
638
+ @model.all(:conditions => @comparison.foreign_key_mapping).should == [ @child ]
639
+ end
640
+ end
641
+ end
642
+
643
+ it { should respond_to(:inspect) }
644
+
645
+ describe '#inspect' do
646
+ subject { @comparison.inspect }
647
+
648
+ it { should == '#<DataMapper::Query::Conditions::InclusionComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:id> @dumped_value=[1] @loaded_value=[1]>' }
649
+ end
650
+
651
+ it { should respond_to(:matches?) }
652
+
653
+ describe '#matches?' do
654
+ supported_by :all do
655
+ describe 'with a Property subject' do
656
+ describe 'with an Array value' do
657
+ describe 'with a matching Hash' do
658
+ subject { @comparison.matches?(@property.field => 1) }
659
+
660
+ it { should be_true }
661
+ end
662
+
663
+ describe 'with a not matching Hash' do
664
+ subject { @comparison.matches?(@property.field => 2) }
665
+
666
+ it { should be_false }
667
+ end
668
+
669
+ describe 'with a matching Resource' do
670
+ subject { @comparison.matches?(@model.new(@property => 1)) }
671
+
672
+ it { should be_true }
673
+ end
674
+
675
+ describe 'with a not matching Resource' do
676
+ subject { @comparison.matches?(@model.new(@property => 2)) }
677
+
678
+ it { should be_false }
679
+ end
680
+ end
681
+
682
+ describe 'with an Array value that needs typecasting' do
683
+ before do
684
+ @value = [ '1' ]
685
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
686
+ end
687
+
688
+ describe 'with a matching Hash' do
689
+ subject { @comparison.matches?(@property.field => 1) }
690
+
691
+ it { should be_true }
692
+ end
693
+
694
+ describe 'with a not matching Hash' do
695
+ subject { @comparison.matches?(@property.field => 2) }
696
+
697
+ it { should be_false }
698
+ end
699
+
700
+ describe 'with a matching Resource' do
701
+ subject { @comparison.matches?(@model.new(@property => 1)) }
702
+
703
+ it { should be_true }
704
+ end
705
+
706
+ describe 'with a not matching Resource' do
707
+ subject { @comparison.matches?(@model.new(@property => 2)) }
708
+
709
+ it { should be_false }
710
+ end
711
+ end
712
+
713
+ describe 'with a Range value' do
714
+ before do
715
+ @value = 1..2
716
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
717
+ end
718
+
719
+ describe 'with a matching Hash' do
720
+ subject { @comparison.matches?(@property.field => 1) }
721
+
722
+ it { should be_true }
723
+ end
724
+
725
+ describe 'with a not matching Hash' do
726
+ subject { @comparison.matches?(@property.field => 0) }
727
+
728
+ it { should be_false }
729
+ end
730
+
731
+ describe 'with a matching Resource' do
732
+ subject { @comparison.matches?(@model.new(@property => 1)) }
733
+
734
+ it { should be_true }
735
+ end
736
+
737
+ describe 'with a not matching Resource' do
738
+ subject { @comparison.matches?(@model.new(@property => 0)) }
739
+
740
+ it { should be_false }
741
+ end
742
+ end
743
+
744
+ describe 'with a Range value that needs typecasting' do
745
+ before do
746
+ @value = '1'...'2'
747
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
748
+ end
749
+
750
+ describe 'with a matching Hash' do
751
+ subject { @comparison.matches?(@property.field => 1) }
752
+
753
+ it { should be_true }
754
+ end
755
+
756
+ describe 'with a not matching Hash' do
757
+ subject { @comparison.matches?(@property.field => 2) }
758
+
759
+ it { should be_false }
760
+ end
761
+
762
+ describe 'with a matching Resource' do
763
+ subject { @comparison.matches?(@model.new(@property => 1)) }
764
+
765
+ it { should be_true }
766
+ end
767
+
768
+ describe 'with a not matching Resource' do
769
+ subject { @comparison.matches?(@model.new(@property => 2)) }
770
+
771
+ it { should be_false }
772
+ end
773
+ end
774
+ end
775
+
776
+ describe 'with a Relationship subject' do
777
+ describe 'with a Hash value' do
778
+ before do
779
+ @parent = @model.create(:title => 'Parent')
780
+ @child = @parent.children.create(:title => 'Child')
781
+
782
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent.attributes.except(:id))
783
+ end
784
+
785
+ describe 'with a matching Hash' do
786
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
787
+
788
+ it { pending { should be_true } }
789
+ end
790
+
791
+ describe 'with a not matching Hash' do
792
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
793
+
794
+ it { should be_false }
795
+ end
796
+
797
+ describe 'with a matching Resource' do
798
+ subject { @comparison.matches?(@child) }
799
+
800
+ it { should be_true }
801
+ end
802
+
803
+ describe 'with a not matching Resource' do
804
+ subject { @comparison.matches?(@parent) }
805
+
806
+ it { should be_false }
807
+ end
808
+ end
809
+
810
+ describe 'with a new Resource value' do
811
+ before do
812
+ @parent = @model.create(:title => 'Parent')
813
+ @child = @parent.children.create(:title => 'Child')
814
+
815
+ new_resource = @model.new(@parent.attributes.except(:id))
816
+
817
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, new_resource)
818
+ end
819
+
820
+ describe 'with a matching Hash' do
821
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
822
+
823
+ it { should be_true }
824
+ end
825
+
826
+ describe 'with a not matching Hash' do
827
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
828
+
829
+ it { pending { should be_false } }
830
+ end
831
+
832
+ describe 'with a matching Resource' do
833
+ subject { @comparison.matches?(@child) }
834
+
835
+ it { pending { should be_true } }
836
+ end
837
+
838
+ describe 'with a not matching Resource' do
839
+ subject { @comparison.matches?(@parent) }
840
+
841
+ it { pending { should be_false } }
842
+ end
843
+ end
844
+
845
+ describe 'with a saved Resource value' do
846
+ before do
847
+ @parent = @model.create(:title => 'Parent')
848
+ @child = @parent.children.create(:title => 'Child')
849
+
850
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent)
851
+ end
852
+
853
+ describe 'with a matching Hash' do
854
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
855
+
856
+ it { pending { should be_true } }
857
+ end
858
+
859
+ describe 'with a not matching Hash' do
860
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
861
+
862
+ it { should be_false }
863
+ end
864
+
865
+ describe 'with a matching Resource' do
866
+ subject { @comparison.matches?(@child) }
867
+
868
+ it { should be_true }
869
+ end
870
+
871
+ describe 'with a not matching Resource' do
872
+ subject { @comparison.matches?(@parent) }
873
+
874
+ it { should be_false }
875
+ end
876
+ end
877
+
878
+ describe 'with a Collection value' do
879
+ before do
880
+ @parent = @model.create(:title => 'Parent')
881
+ @child = @parent.children.create(:title => 'Child')
882
+
883
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @model.all(:title => 'Parent'))
884
+ end
885
+
886
+ describe 'with a matching Hash' do
887
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
888
+
889
+ it { pending { should be_true } }
890
+ end
891
+
892
+ describe 'with a not matching Hash' do
893
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
894
+
895
+ it { should be_false }
896
+ end
897
+
898
+ describe 'with a matching Resource' do
899
+ subject { @comparison.matches?(@child) }
900
+
901
+ it { should be_true }
902
+ end
903
+
904
+ describe 'with a not matching Resource' do
905
+ subject { @comparison.matches?(@parent) }
906
+
907
+ it { should be_false }
908
+ end
909
+ end
910
+
911
+ describe 'with an Enumerable value containing a Hash' do
912
+ before do
913
+ @parent = @model.create(:title => 'Parent')
914
+ @child = @parent.children.create(:title => 'Child')
915
+
916
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, [ @parent.attributes.except(:id), { :title => 'Other' } ])
917
+ end
918
+
919
+ describe 'with a matching Hash' do
920
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
921
+
922
+ it { pending { should be_true } }
923
+ end
924
+
925
+ describe 'with a not matching Hash' do
926
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
927
+
928
+ it { should be_false }
929
+ end
930
+
931
+ describe 'with a matching Resource' do
932
+ subject { @comparison.matches?(@child) }
933
+
934
+ it { should be_true }
935
+ end
936
+
937
+ describe 'with a not matching Resource' do
938
+ subject { @comparison.matches?(@parent) }
939
+
940
+ it { should be_false }
941
+ end
942
+ end
943
+
944
+ describe 'with an Enumerable value containing a new Resource' do
945
+ before do
946
+ @parent = @model.create(:title => 'Parent')
947
+ @child = @parent.children.create(:title => 'Child')
948
+
949
+ new_resource = @model.new(@parent.attributes.except(:id))
950
+
951
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, [ new_resource ])
952
+ end
953
+
954
+ describe 'with a matching Hash' do
955
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
956
+
957
+ it { should be_true }
958
+ end
959
+
960
+ describe 'with a not matching Hash' do
961
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
962
+
963
+ it { pending { should be_false } }
964
+ end
965
+
966
+ describe 'with a matching Resource' do
967
+ subject { @comparison.matches?(@child) }
968
+
969
+ it { pending { should be_true } }
970
+ end
971
+
972
+ describe 'with a not matching Resource' do
973
+ subject { @comparison.matches?(@parent) }
974
+
975
+ it { pending { should be_false } }
976
+ end
977
+ end
978
+
979
+ describe 'with an Enumerable value containing a saved Resource' do
980
+ before do
981
+ @parent = @model.create(:title => 'Parent')
982
+ @child = @parent.children.create(:title => 'Child')
983
+
984
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, [ @parent ])
985
+ end
986
+
987
+ describe 'with a matching Hash' do
988
+ subject { @comparison.matches?({ @relationship.field => @parent.attributes(:field) }) }
989
+
990
+ it { pending { should be_true } }
991
+ end
992
+
993
+ describe 'with a not matching Hash' do
994
+ subject { @comparison.matches?({ @relationship.field => @child.attributes(:field) }) }
995
+
996
+ it { should be_false }
997
+ end
998
+
999
+ describe 'with a matching Resource' do
1000
+ subject { @comparison.matches?(@child) }
1001
+
1002
+ it { should be_true }
1003
+ end
1004
+
1005
+ describe 'with a not matching Resource' do
1006
+ subject { @comparison.matches?(@parent) }
1007
+
1008
+ it { should be_false }
1009
+ end
1010
+ end
1011
+ end
1012
+ end
1013
+ end
1014
+
1015
+ it { should respond_to(:relationship?) }
1016
+
1017
+ describe '#relationship?' do
1018
+ subject { @comparison.relationship? }
1019
+
1020
+ it { should be_false }
1021
+ end
1022
+
1023
+ it { should respond_to(:to_s) }
1024
+
1025
+ describe '#to_s' do
1026
+ subject { @comparison.to_s }
1027
+
1028
+ it { should == 'id IN [1]' }
1029
+ end
1030
+
1031
+ it { should respond_to(:valid?) }
1032
+
1033
+ describe '#valid?' do
1034
+ subject { @comparison.valid? }
1035
+
1036
+ describe 'with a Property subject' do
1037
+ describe 'with a valid Array value' do
1038
+ it { should be_true }
1039
+ end
1040
+
1041
+ describe 'with a valid Array value that needs typecasting' do
1042
+ before do
1043
+ @value = [ '1' ]
1044
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1045
+ end
1046
+
1047
+ it { should be_true }
1048
+ end
1049
+
1050
+ describe 'with an invalid Array value' do
1051
+ before do
1052
+ @value = [ 'invalid' ]
1053
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1054
+ end
1055
+
1056
+ it { should be_false }
1057
+ end
1058
+
1059
+ describe 'with an empty Array value' do
1060
+ before do
1061
+ @value = []
1062
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1063
+ end
1064
+
1065
+ it { should be_false }
1066
+ end
1067
+
1068
+ describe 'with a valid Range value' do
1069
+ before do
1070
+ @value = 1..1
1071
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1072
+ end
1073
+
1074
+ it { should be_true }
1075
+ end
1076
+
1077
+ describe 'with a valid Range value that needs typecasting' do
1078
+ before do
1079
+ @value = '1'...'2'
1080
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1081
+ end
1082
+
1083
+ it { should be_true }
1084
+ end
1085
+
1086
+ describe 'with an invalid Range value' do
1087
+ before do
1088
+ @value = 'a'..'z'
1089
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1090
+ end
1091
+
1092
+ it { should be_false }
1093
+ end
1094
+
1095
+ describe 'with an empty Range value' do
1096
+ before do
1097
+ @value = 1..0
1098
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1099
+ end
1100
+
1101
+ it { should be_false }
1102
+ end
1103
+ end
1104
+
1105
+ describe 'with a Relationship subject' do
1106
+ describe 'with a valid Array value' do
1107
+ before do
1108
+ @value = [ @model.new(:id => 1) ]
1109
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @value)
1110
+ end
1111
+
1112
+ it { should be_true }
1113
+ end
1114
+
1115
+ describe 'with an invalid Array value' do
1116
+ before do
1117
+ @value = [ @model.new ]
1118
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @value)
1119
+ end
1120
+
1121
+ it { should be_false }
1122
+ end
1123
+
1124
+ describe 'with an empty Array value' do
1125
+ before do
1126
+ @value = []
1127
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @value)
1128
+ end
1129
+
1130
+ it { should be_false }
1131
+ end
1132
+
1133
+ describe 'with a valid Collection' do
1134
+ before do
1135
+ @value = @model.all
1136
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @value)
1137
+ end
1138
+
1139
+ it { should be_true }
1140
+ end
1141
+ end
1142
+ end
1143
+
1144
+ it { should respond_to(:value) }
1145
+
1146
+ describe '#value' do
1147
+ supported_by :all do
1148
+ subject { @comparison.value }
1149
+
1150
+ describe 'with a Property subject' do
1151
+ describe 'with an Array value' do
1152
+ before do
1153
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, [ 1, 1 ])
1154
+ end
1155
+
1156
+ it { should be_kind_of(Array) }
1157
+
1158
+ it { should == @value }
1159
+ end
1160
+
1161
+ describe 'with a Range value' do
1162
+ before do
1163
+ @value = 1..1
1164
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1165
+ end
1166
+
1167
+ it { should be_kind_of(Range) }
1168
+
1169
+ it { should == @value }
1170
+ end
1171
+ end
1172
+
1173
+ describe 'with a Relationship subject' do
1174
+ before :all do
1175
+ @parent = @model.create(:title => 'Parent')
1176
+ @child = @parent.children.create(:title => 'Child')
1177
+ end
1178
+
1179
+ describe 'with an Hash value' do
1180
+ before do
1181
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, :id => @parent.id)
1182
+ end
1183
+
1184
+ it { should be_kind_of(DataMapper::Collection) }
1185
+
1186
+ it { should == [ @parent ] }
1187
+ end
1188
+
1189
+ describe 'with an Array value' do
1190
+ before do
1191
+ @value = [ @parent ]
1192
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @value)
1193
+ end
1194
+
1195
+ it { should be_kind_of(DataMapper::Collection) }
1196
+
1197
+ it { should == @value }
1198
+ end
1199
+
1200
+ describe 'with a Resource value' do
1201
+ before do
1202
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @parent)
1203
+ end
1204
+
1205
+ it { should be_kind_of(DataMapper::Collection) }
1206
+
1207
+ it { should == [ @parent ] }
1208
+ end
1209
+
1210
+ describe 'with a Collection value' do
1211
+ before do
1212
+ @value = @model.all
1213
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @relationship, @value)
1214
+ end
1215
+
1216
+ it 'should not be a kicker' do
1217
+ @value.should_not be_loaded
1218
+ end
1219
+
1220
+ it { should be_kind_of(DataMapper::Collection) }
1221
+
1222
+ it { should == @value }
1223
+ end
1224
+ end
1225
+ end
1226
+ end
1227
+ end
1228
+
1229
+ describe DataMapper::Query::Conditions::RegexpComparison do
1230
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
1231
+
1232
+ before do
1233
+ @property = @model.properties[:title]
1234
+ @other_property = @model.properties[:id]
1235
+ @value = /Title/
1236
+ @other_value = /Other Title/
1237
+ @slug = :regexp
1238
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1239
+ @other = OtherComparison.new(@property, @value)
1240
+ end
1241
+
1242
+ subject { @comparison }
1243
+
1244
+ it { should respond_to(:inspect) }
1245
+
1246
+ describe '#inspect' do
1247
+ subject { @comparison.inspect }
1248
+
1249
+ it { should == '#<DataMapper::Query::Conditions::RegexpComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:title> @dumped_value=/Title/ @loaded_value=/Title/>' }
1250
+ end
1251
+
1252
+ it { should respond_to(:matches?) }
1253
+
1254
+ describe '#matches?' do
1255
+ supported_by :all do
1256
+ describe 'with a matching Hash' do
1257
+ subject { @comparison.matches?(@property.field => 'Title') }
1258
+
1259
+ it { should be_true }
1260
+ end
1261
+
1262
+ describe 'with a not matching Hash' do
1263
+ subject { @comparison.matches?(@property.field => 'Other') }
1264
+
1265
+ it { should be_false }
1266
+ end
1267
+
1268
+ describe 'with a matching Resource' do
1269
+ subject { @comparison.matches?(@model.new(@property => 'Title')) }
1270
+
1271
+ it { should be_true }
1272
+ end
1273
+
1274
+ describe 'with a not matching Resource' do
1275
+ subject { @comparison.matches?(@model.new(@property => 'Other')) }
1276
+
1277
+ it { should be_false }
1278
+ end
1279
+
1280
+ describe 'with a not matching nil field' do
1281
+ subject { @comparison.matches?(@property.field => nil) }
1282
+
1283
+ it { should be_false }
1284
+ end
1285
+
1286
+ describe 'with a not matching nil attribute' do
1287
+ subject { @comparison.matches?(@model.new(@property => nil)) }
1288
+
1289
+ it { should be_false }
1290
+ end
1291
+ end
1292
+ end
1293
+
1294
+ it { should respond_to(:relationship?) }
1295
+
1296
+ describe '#relationship?' do
1297
+ subject { @comparison.relationship? }
1298
+
1299
+ it { should be_false }
1300
+ end
1301
+
1302
+ it { should respond_to(:to_s) }
1303
+
1304
+ describe '#to_s' do
1305
+ subject { @comparison.to_s }
1306
+
1307
+ it { should == 'title =~ /Title/' }
1308
+ end
1309
+ end
1310
+
1311
+ describe DataMapper::Query::Conditions::LikeComparison do
1312
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
1313
+
1314
+ before do
1315
+ @property = @model.properties[:title]
1316
+ @other_property = @model.properties[:id]
1317
+ @value = '_it%'
1318
+ @other_value = 'Other Title'
1319
+ @slug = :like
1320
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1321
+ @other = OtherComparison.new(@property, @value)
1322
+ end
1323
+
1324
+ subject { @comparison }
1325
+
1326
+ it { should respond_to(:inspect) }
1327
+
1328
+ describe '#inspect' do
1329
+ subject { @comparison.inspect }
1330
+
1331
+ it { should == '#<DataMapper::Query::Conditions::LikeComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:title> @dumped_value="_it%" @loaded_value="_it%">' }
1332
+ end
1333
+
1334
+ it { should respond_to(:matches?) }
1335
+
1336
+ describe '#matches?' do
1337
+ supported_by :all do
1338
+ describe 'with a matching Hash' do
1339
+ subject { @comparison.matches?(@property.field => 'Title') }
1340
+
1341
+ it { should be_true }
1342
+ end
1343
+
1344
+ describe 'with a not matching Hash' do
1345
+ subject { @comparison.matches?(@property.field => 'Other Title') }
1346
+
1347
+ it { should be_false }
1348
+ end
1349
+
1350
+ describe 'with a matching Resource' do
1351
+ subject { @comparison.matches?(@model.new(@property => 'Title')) }
1352
+
1353
+ it { should be_true }
1354
+ end
1355
+
1356
+ describe 'with a not matching Resource' do
1357
+ subject { @comparison.matches?(@model.new(@property => 'Other Title')) }
1358
+
1359
+ it { should be_false }
1360
+ end
1361
+
1362
+ describe 'with a not matching nil field' do
1363
+ subject { @comparison.matches?(@property.field => nil) }
1364
+
1365
+ it { should be_false }
1366
+ end
1367
+
1368
+ describe 'with a not matching nil attribute' do
1369
+ subject { @comparison.matches?(@model.new(@property => nil)) }
1370
+
1371
+ it { should be_false }
1372
+ end
1373
+ end
1374
+ end
1375
+
1376
+ it { should respond_to(:relationship?) }
1377
+
1378
+ describe '#relationship?' do
1379
+ subject { @comparison.relationship? }
1380
+
1381
+ it { should be_false }
1382
+ end
1383
+
1384
+ it { should respond_to(:to_s) }
1385
+
1386
+ describe '#to_s' do
1387
+ subject { @comparison.to_s }
1388
+
1389
+ it { should == 'title LIKE "_it%"' }
1390
+ end
1391
+ end
1392
+
1393
+ describe DataMapper::Query::Conditions::GreaterThanComparison do
1394
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
1395
+
1396
+ before do
1397
+ @property = @model.properties[:id]
1398
+ @other_property = @model.properties[:title]
1399
+ @value = 1
1400
+ @other_value = 2
1401
+ @slug = :gt
1402
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1403
+ @other = OtherComparison.new(@property, @value)
1404
+ end
1405
+
1406
+ subject { @comparison }
1407
+
1408
+ it { should respond_to(:inspect) }
1409
+
1410
+ describe '#inspect' do
1411
+ subject { @comparison.inspect }
1412
+
1413
+ it { should == '#<DataMapper::Query::Conditions::GreaterThanComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:id> @dumped_value=1 @loaded_value=1>' }
1414
+ end
1415
+
1416
+ it { should respond_to(:matches?) }
1417
+
1418
+ describe '#matches?' do
1419
+ supported_by :all do
1420
+ describe 'with a matching Hash' do
1421
+ subject { @comparison.matches?(@property.field => 2) }
1422
+
1423
+ it { should be_true }
1424
+ end
1425
+
1426
+ describe 'with a not matching Hash' do
1427
+ subject { @comparison.matches?(@property.field => 1) }
1428
+
1429
+ it { should be_false }
1430
+ end
1431
+
1432
+ describe 'with a matching Resource' do
1433
+ subject { @comparison.matches?(@model.new(@property => 2)) }
1434
+
1435
+ it { should be_true }
1436
+ end
1437
+
1438
+ describe 'with a not matching Resource' do
1439
+ subject { @comparison.matches?(@model.new(@property => 1)) }
1440
+
1441
+ it { should be_false }
1442
+ end
1443
+
1444
+ describe 'with a not matching nil field' do
1445
+ subject { @comparison.matches?(@property.field => nil) }
1446
+
1447
+ it { should be_false }
1448
+ end
1449
+
1450
+ describe 'with a not matching nil attribute' do
1451
+ subject { @comparison.matches?(@model.new(@property => nil)) }
1452
+
1453
+ it { should be_false }
1454
+ end
1455
+ end
1456
+ end
1457
+
1458
+ it { should respond_to(:relationship?) }
1459
+
1460
+ describe '#relationship?' do
1461
+ subject { @comparison.relationship? }
1462
+
1463
+ it { should be_false }
1464
+ end
1465
+
1466
+ it { should respond_to(:to_s) }
1467
+
1468
+ describe '#to_s' do
1469
+ subject { @comparison.to_s }
1470
+
1471
+ it { should == 'id > 1' }
1472
+ end
1473
+ end
1474
+
1475
+ describe DataMapper::Query::Conditions::LessThanComparison do
1476
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
1477
+
1478
+ before do
1479
+ @property = @model.properties[:id]
1480
+ @other_property = @model.properties[:title]
1481
+ @value = 1
1482
+ @other_value = 2
1483
+ @slug = :lt
1484
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1485
+ @other = OtherComparison.new(@property, @value)
1486
+ end
1487
+
1488
+ subject { @comparison }
1489
+
1490
+ it { should respond_to(:inspect) }
1491
+
1492
+ describe '#inspect' do
1493
+ subject { @comparison.inspect }
1494
+
1495
+ it { should == '#<DataMapper::Query::Conditions::LessThanComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:id> @dumped_value=1 @loaded_value=1>' }
1496
+ end
1497
+
1498
+ it { should respond_to(:matches?) }
1499
+
1500
+ describe '#matches?' do
1501
+ supported_by :all do
1502
+ describe 'with a matching Hash' do
1503
+ subject { @comparison.matches?(@property.field => 0) }
1504
+
1505
+ it { should be_true }
1506
+ end
1507
+
1508
+ describe 'with a not matching Hash' do
1509
+ subject { @comparison.matches?(@property.field => 1) }
1510
+
1511
+ it { should be_false }
1512
+ end
1513
+
1514
+ describe 'with a matching Resource' do
1515
+ subject { @comparison.matches?(@model.new(@property => 0)) }
1516
+
1517
+ it { should be_true }
1518
+ end
1519
+
1520
+ describe 'with a not matching Resource' do
1521
+ subject { @comparison.matches?(@model.new(@property => 1)) }
1522
+
1523
+ it { should be_false }
1524
+ end
1525
+
1526
+ describe 'with a not matching nil field' do
1527
+ subject { @comparison.matches?(@property.field => nil) }
1528
+
1529
+ it { should be_false }
1530
+ end
1531
+
1532
+ describe 'with a not matching nil attribute' do
1533
+ subject { @comparison.matches?(@model.new(@property => nil)) }
1534
+
1535
+ it { should be_false }
1536
+ end
1537
+ end
1538
+ end
1539
+
1540
+ it { should respond_to(:relationship?) }
1541
+
1542
+ describe '#relationship?' do
1543
+ subject { @comparison.relationship? }
1544
+
1545
+ it { should be_false }
1546
+ end
1547
+
1548
+ it { should respond_to(:to_s) }
1549
+
1550
+ describe '#to_s' do
1551
+ subject { @comparison.to_s }
1552
+
1553
+ it { should == 'id < 1' }
1554
+ end
1555
+ end
1556
+
1557
+ describe DataMapper::Query::Conditions::GreaterThanOrEqualToComparison do
1558
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
1559
+
1560
+ before do
1561
+ @property = @model.properties[:id]
1562
+ @other_property = @model.properties[:title]
1563
+ @value = 1
1564
+ @other_value = 2
1565
+ @slug = :gte
1566
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1567
+ @other = OtherComparison.new(@property, @value)
1568
+ end
1569
+
1570
+ subject { @comparison }
1571
+
1572
+ it { should respond_to(:inspect) }
1573
+
1574
+ describe '#inspect' do
1575
+ subject { @comparison.inspect }
1576
+
1577
+ it { should == '#<DataMapper::Query::Conditions::GreaterThanOrEqualToComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:id> @dumped_value=1 @loaded_value=1>' }
1578
+ end
1579
+
1580
+ it { should respond_to(:matches?) }
1581
+
1582
+ describe '#matches?' do
1583
+ supported_by :all do
1584
+ describe 'with a matching Hash' do
1585
+ subject { @comparison.matches?(@property.field => 1) }
1586
+
1587
+ it { should be_true }
1588
+ end
1589
+
1590
+ describe 'with a not matching Hash' do
1591
+ subject { @comparison.matches?(@property.field => 0) }
1592
+
1593
+ it { should be_false }
1594
+ end
1595
+
1596
+ describe 'with a matching Resource' do
1597
+ subject { @comparison.matches?(@model.new(@property => 1)) }
1598
+
1599
+ it { should be_true }
1600
+ end
1601
+
1602
+ describe 'with a not matching Resource' do
1603
+ subject { @comparison.matches?(@model.new(@property => 0)) }
1604
+
1605
+ it { should be_false }
1606
+ end
1607
+
1608
+ describe 'with a not matching nil field' do
1609
+ subject { @comparison.matches?(@property.field => nil) }
1610
+
1611
+ it { should be_false }
1612
+ end
1613
+
1614
+ describe 'with a not matching nil attribute' do
1615
+ subject { @comparison.matches?(@model.new(@property => nil)) }
1616
+
1617
+ it { should be_false }
1618
+ end
1619
+ end
1620
+ end
1621
+
1622
+ it { should respond_to(:relationship?) }
1623
+
1624
+ describe '#relationship?' do
1625
+ subject { @comparison.relationship? }
1626
+
1627
+ it { should be_false }
1628
+ end
1629
+
1630
+ it { should respond_to(:to_s) }
1631
+
1632
+ describe '#to_s' do
1633
+ subject { @comparison.to_s }
1634
+
1635
+ it { should == 'id >= 1' }
1636
+ end
1637
+ end
1638
+
1639
+ describe DataMapper::Query::Conditions::LessThanOrEqualToComparison do
1640
+ it_should_behave_like 'DataMapper::Query::Conditions::AbstractComparison'
1641
+
1642
+ before do
1643
+ @property = @model.properties[:id]
1644
+ @other_property = @model.properties[:title]
1645
+ @value = 1
1646
+ @other_value = 2
1647
+ @slug = :lte
1648
+ @comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)
1649
+ @other = OtherComparison.new(@property, @value)
1650
+ end
1651
+
1652
+ subject { @comparison }
1653
+
1654
+ it { should respond_to(:inspect) }
1655
+
1656
+ describe '#inspect' do
1657
+ subject { @comparison.inspect }
1658
+
1659
+ it { should == '#<DataMapper::Query::Conditions::LessThanOrEqualToComparison @subject=#<DataMapper::Property @model=Blog::Article @name=:id> @dumped_value=1 @loaded_value=1>' }
1660
+ end
1661
+
1662
+ it { should respond_to(:matches?) }
1663
+
1664
+ describe '#matches?' do
1665
+ supported_by :all do
1666
+ describe 'with a matching Hash' do
1667
+ subject { @comparison.matches?(@property.field => 1) }
1668
+
1669
+ it { should be_true }
1670
+ end
1671
+
1672
+ describe 'with a not matching Hash' do
1673
+ subject { @comparison.matches?(@property.field => 2) }
1674
+
1675
+ it { should be_false }
1676
+ end
1677
+
1678
+ describe 'with a matching Resource' do
1679
+ subject { @comparison.matches?(@model.new(@property => 1)) }
1680
+
1681
+ it { should be_true }
1682
+ end
1683
+
1684
+ describe 'with a not matching Resource' do
1685
+ subject { @comparison.matches?(@model.new(@property => 2)) }
1686
+
1687
+ it { should be_false }
1688
+ end
1689
+
1690
+ describe 'with a not matching nil field' do
1691
+ subject { @comparison.matches?(@property.field => nil) }
1692
+
1693
+ it { should be_false }
1694
+ end
1695
+
1696
+ describe 'with a not matching nil attribute' do
1697
+ subject { @comparison.matches?(@model.new(@property => nil)) }
1698
+
1699
+ it { should be_false }
1700
+ end
1701
+ end
1702
+ end
1703
+
1704
+ it { should respond_to(:relationship?) }
1705
+
1706
+ describe '#relationship?' do
1707
+ subject { @comparison.relationship? }
1708
+
1709
+ it { should be_false }
1710
+ end
1711
+
1712
+ it { should respond_to(:to_s) }
1713
+
1714
+ describe '#to_s' do
1715
+ subject { @comparison.to_s }
1716
+
1717
+ it { should == 'id <= 1' }
1718
+ end
1719
+ end