sam-dm-core 0.9.6
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.
- data/.autotest +26 -0
- data/CONTRIBUTING +51 -0
- data/FAQ +92 -0
- data/History.txt +145 -0
- data/MIT-LICENSE +22 -0
- data/Manifest.txt +125 -0
- data/QUICKLINKS +12 -0
- data/README.txt +143 -0
- data/Rakefile +30 -0
- data/SPECS +63 -0
- data/TODO +1 -0
- data/lib/dm-core.rb +224 -0
- data/lib/dm-core/adapters.rb +4 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +202 -0
- data/lib/dm-core/adapters/data_objects_adapter.rb +707 -0
- data/lib/dm-core/adapters/mysql_adapter.rb +136 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +188 -0
- data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
- data/lib/dm-core/associations.rb +199 -0
- data/lib/dm-core/associations/many_to_many.rb +147 -0
- data/lib/dm-core/associations/many_to_one.rb +107 -0
- data/lib/dm-core/associations/one_to_many.rb +309 -0
- data/lib/dm-core/associations/one_to_one.rb +61 -0
- data/lib/dm-core/associations/relationship.rb +218 -0
- data/lib/dm-core/associations/relationship_chain.rb +81 -0
- data/lib/dm-core/auto_migrations.rb +113 -0
- data/lib/dm-core/collection.rb +638 -0
- data/lib/dm-core/dependency_queue.rb +31 -0
- data/lib/dm-core/hook.rb +11 -0
- data/lib/dm-core/identity_map.rb +45 -0
- data/lib/dm-core/is.rb +16 -0
- data/lib/dm-core/logger.rb +232 -0
- data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
- data/lib/dm-core/migrator.rb +29 -0
- data/lib/dm-core/model.rb +471 -0
- data/lib/dm-core/naming_conventions.rb +84 -0
- data/lib/dm-core/property.rb +673 -0
- data/lib/dm-core/property_set.rb +162 -0
- data/lib/dm-core/query.rb +625 -0
- data/lib/dm-core/repository.rb +159 -0
- data/lib/dm-core/resource.rb +637 -0
- data/lib/dm-core/scope.rb +58 -0
- data/lib/dm-core/support.rb +7 -0
- data/lib/dm-core/support/array.rb +13 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/errors.rb +23 -0
- data/lib/dm-core/support/kernel.rb +7 -0
- data/lib/dm-core/support/symbol.rb +41 -0
- data/lib/dm-core/transaction.rb +267 -0
- data/lib/dm-core/type.rb +160 -0
- data/lib/dm-core/type_map.rb +80 -0
- data/lib/dm-core/types.rb +19 -0
- data/lib/dm-core/types/boolean.rb +7 -0
- data/lib/dm-core/types/discriminator.rb +34 -0
- data/lib/dm-core/types/object.rb +24 -0
- data/lib/dm-core/types/paranoid_boolean.rb +34 -0
- data/lib/dm-core/types/paranoid_datetime.rb +33 -0
- data/lib/dm-core/types/serial.rb +9 -0
- data/lib/dm-core/types/text.rb +10 -0
- data/lib/dm-core/version.rb +3 -0
- data/script/all +5 -0
- data/script/performance.rb +203 -0
- data/script/profile.rb +87 -0
- data/spec/integration/association_spec.rb +1371 -0
- data/spec/integration/association_through_spec.rb +203 -0
- data/spec/integration/associations/many_to_many_spec.rb +449 -0
- data/spec/integration/associations/many_to_one_spec.rb +163 -0
- data/spec/integration/associations/one_to_many_spec.rb +151 -0
- data/spec/integration/auto_migrations_spec.rb +398 -0
- data/spec/integration/collection_spec.rb +1069 -0
- data/spec/integration/data_objects_adapter_spec.rb +32 -0
- data/spec/integration/dependency_queue_spec.rb +58 -0
- data/spec/integration/model_spec.rb +127 -0
- data/spec/integration/mysql_adapter_spec.rb +85 -0
- data/spec/integration/postgres_adapter_spec.rb +731 -0
- data/spec/integration/property_spec.rb +233 -0
- data/spec/integration/query_spec.rb +506 -0
- data/spec/integration/repository_spec.rb +57 -0
- data/spec/integration/resource_spec.rb +475 -0
- data/spec/integration/sqlite3_adapter_spec.rb +352 -0
- data/spec/integration/sti_spec.rb +208 -0
- data/spec/integration/strategic_eager_loading_spec.rb +138 -0
- data/spec/integration/transaction_spec.rb +75 -0
- data/spec/integration/type_spec.rb +271 -0
- data/spec/lib/logging_helper.rb +18 -0
- data/spec/lib/mock_adapter.rb +27 -0
- data/spec/lib/model_loader.rb +91 -0
- data/spec/lib/publicize_methods.rb +28 -0
- data/spec/models/vehicles.rb +34 -0
- data/spec/models/zoo.rb +47 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
- data/spec/unit/adapters/data_objects_adapter_spec.rb +628 -0
- data/spec/unit/adapters/postgres_adapter_spec.rb +133 -0
- data/spec/unit/associations/many_to_many_spec.rb +17 -0
- data/spec/unit/associations/many_to_one_spec.rb +152 -0
- data/spec/unit/associations/one_to_many_spec.rb +393 -0
- data/spec/unit/associations/one_to_one_spec.rb +7 -0
- data/spec/unit/associations/relationship_spec.rb +71 -0
- data/spec/unit/associations_spec.rb +242 -0
- data/spec/unit/auto_migrations_spec.rb +111 -0
- data/spec/unit/collection_spec.rb +182 -0
- data/spec/unit/data_mapper_spec.rb +35 -0
- data/spec/unit/identity_map_spec.rb +126 -0
- data/spec/unit/is_spec.rb +80 -0
- data/spec/unit/migrator_spec.rb +33 -0
- data/spec/unit/model_spec.rb +339 -0
- data/spec/unit/naming_conventions_spec.rb +36 -0
- data/spec/unit/property_set_spec.rb +83 -0
- data/spec/unit/property_spec.rb +753 -0
- data/spec/unit/query_spec.rb +530 -0
- data/spec/unit/repository_spec.rb +93 -0
- data/spec/unit/resource_spec.rb +626 -0
- data/spec/unit/scope_spec.rb +142 -0
- data/spec/unit/transaction_spec.rb +493 -0
- data/spec/unit/type_map_spec.rb +114 -0
- data/spec/unit/type_spec.rb +119 -0
- data/tasks/ci.rb +68 -0
- data/tasks/dm.rb +63 -0
- data/tasks/doc.rb +20 -0
- data/tasks/gemspec.rb +23 -0
- data/tasks/hoe.rb +46 -0
- data/tasks/install.rb +20 -0
- metadata +216 -0
@@ -0,0 +1,530 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
GOOD_OPTIONS = [
|
4
|
+
[ :reload, false ],
|
5
|
+
[ :reload, true ],
|
6
|
+
[ :offset, 0 ],
|
7
|
+
[ :offset, 1 ],
|
8
|
+
[ :limit, 1 ],
|
9
|
+
[ :limit, 2 ],
|
10
|
+
[ :order, [ DataMapper::Query::Direction.new(Article.properties[:created_at], :desc) ] ],
|
11
|
+
[ :fields, Article.properties.defaults.to_a ], # TODO: fill in allowed default value
|
12
|
+
#[ :links, [ :stub ] ], # TODO: fill in allowed default value
|
13
|
+
[ :includes, [ :stub ] ], # TODO: fill in allowed default value
|
14
|
+
]
|
15
|
+
|
16
|
+
BAD_OPTIONS = {
|
17
|
+
:reload => 'true',
|
18
|
+
:offset => -1,
|
19
|
+
:limit => 0,
|
20
|
+
# :order => [], # TODO: spec conditions where :order may be empty
|
21
|
+
# :fields => [], # TODO: spec conditions where :fields may be empty
|
22
|
+
:links => [],
|
23
|
+
:includes => [],
|
24
|
+
:conditions => [],
|
25
|
+
}
|
26
|
+
|
27
|
+
# flatten GOOD_OPTIONS into a Hash to remove default values, since
|
28
|
+
# default value, when defined, is always listed first in GOOD_OPTIONS
|
29
|
+
UPDATED_OPTIONS = GOOD_OPTIONS.inject({}) do |options,(attribute,value)|
|
30
|
+
options.update attribute => value
|
31
|
+
end
|
32
|
+
|
33
|
+
UPDATED_OPTIONS.merge!({ :fields => [ :id, :author ]})
|
34
|
+
|
35
|
+
describe DataMapper::Query do
|
36
|
+
before do
|
37
|
+
@adapter = mock('adapter')
|
38
|
+
@repository = mock('repository', :kind_of? => true, :name => 'mock', :adapter => @adapter)
|
39
|
+
|
40
|
+
@query = DataMapper::Query.new(@repository, Article)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should provide .new' do
|
44
|
+
DataMapper::Query.should respond_to(:new)
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '.new' do
|
48
|
+
describe 'should set the attribute' do
|
49
|
+
it '#model with model' do
|
50
|
+
query = DataMapper::Query.new(@repository, Article)
|
51
|
+
query.model.should == Article
|
52
|
+
end
|
53
|
+
|
54
|
+
GOOD_OPTIONS.each do |(attribute,value)|
|
55
|
+
it "##{attribute} with options[:#{attribute}] if it is #{value.inspect}" do
|
56
|
+
query = DataMapper::Query.new(@repository, Article, attribute => value)
|
57
|
+
query.send(attribute == :reload ? :reload? : attribute).should == value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ' #conditions with options[:conditions]' do
|
62
|
+
it 'when they are a Hash' do
|
63
|
+
query = DataMapper::Query.new(@repository, Article, :conditions => { :author => 'dkubb' })
|
64
|
+
query.conditions.should == [ [ :eql, Article.properties[:author], 'dkubb' ] ]
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'when they have a one element Array' do
|
68
|
+
query = DataMapper::Query.new(@repository, Article, :conditions => [ 'name = "dkubb"' ])
|
69
|
+
query.conditions.should == [ [ :raw, 'name = "dkubb"' ] ]
|
70
|
+
query.bind_values.should == []
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'when they have a two or more element Array' do
|
74
|
+
bind_values = %w[ dkubb ]
|
75
|
+
query = DataMapper::Query.new(@repository, Article, :conditions => [ 'name = ?', *bind_values ])
|
76
|
+
query.conditions.should == [ [ :raw, 'name = ?', bind_values ] ]
|
77
|
+
query.bind_values.should == bind_values
|
78
|
+
|
79
|
+
bind_values = [ 'dkubb', 32 ]
|
80
|
+
query = DataMapper::Query.new(@repository, Article, :conditions => [ 'name = ? OR age = ?', *bind_values ])
|
81
|
+
query.conditions.should == [ [ :raw, 'name = ? OR age = ?', bind_values ] ]
|
82
|
+
query.bind_values.should == bind_values
|
83
|
+
|
84
|
+
bind_values = [ %w[ dkubb ssmoot ] ]
|
85
|
+
query = DataMapper::Query.new(@repository, Article, :conditions => [ 'name IN ?', *bind_values ])
|
86
|
+
query.conditions.should == [ [ :raw, 'name IN ?', bind_values ] ]
|
87
|
+
query.bind_values.should == bind_values
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'when they have another DM:Query as the value of sub-select' do
|
91
|
+
class Acl
|
92
|
+
include DataMapper::Resource
|
93
|
+
property :id, Integer
|
94
|
+
property :resource_id, Integer
|
95
|
+
end
|
96
|
+
|
97
|
+
acl_query = DataMapper::Query.new(@repository, Acl, :fields=>[:resource_id]) #this would normally have conditions
|
98
|
+
query = DataMapper::Query.new(@repository, Article, :id.in => acl_query)
|
99
|
+
query.conditions.each do |operator, property, value|
|
100
|
+
operator.should == :in
|
101
|
+
property.name.should == :id
|
102
|
+
value.should == acl_query
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe ' #conditions with unknown options' do
|
108
|
+
it 'when a Symbol object is a key' do
|
109
|
+
query = DataMapper::Query.new(@repository, Article, :author => 'dkubb')
|
110
|
+
query.conditions.should == [ [ :eql, Article.properties[:author], 'dkubb' ] ]
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'when a Query::Operator object is a key' do
|
114
|
+
query = DataMapper::Query.new(@repository, Article, :author.like => /\Ad(?:an\.)kubb\z/)
|
115
|
+
query.conditions.should == [ [ :like, Article.properties[:author], /\Ad(?:an\.)kubb\z/ ] ]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it '#order with model.default_order if none provided' do
|
120
|
+
query = DataMapper::Query.new(@repository, Article)
|
121
|
+
query.order.should == [ DataMapper::Query::Direction.new(Article.properties[:id], :asc) ]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'should raise an ArgumentError' do
|
126
|
+
it 'when repository is nil' do
|
127
|
+
lambda {
|
128
|
+
DataMapper::Query.new(nil, NormalClass)
|
129
|
+
}.should raise_error(ArgumentError)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'when model is nil' do
|
133
|
+
lambda {
|
134
|
+
DataMapper::Query.new(@repository, nil)
|
135
|
+
}.should raise_error(ArgumentError)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'when model is a Class that does not include DataMapper::Resource' do
|
139
|
+
lambda {
|
140
|
+
DataMapper::Query.new(@repository, NormalClass)
|
141
|
+
}.should raise_error(ArgumentError)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'when options is not a Hash' do
|
145
|
+
lambda {
|
146
|
+
DataMapper::Query.new(@repository, Article, nil)
|
147
|
+
}.should raise_error(ArgumentError)
|
148
|
+
end
|
149
|
+
|
150
|
+
BAD_OPTIONS.each do |attribute,value|
|
151
|
+
it "when options[:#{attribute}] is nil" do
|
152
|
+
lambda {
|
153
|
+
DataMapper::Query.new(@repository, Article, attribute => nil)
|
154
|
+
}.should raise_error(ArgumentError)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "when options[:#{attribute}] is #{value.kind_of?(Array) && value.empty? ? 'an empty Array' : value.inspect}" do
|
158
|
+
lambda {
|
159
|
+
DataMapper::Query.new(@repository, Article, attribute => value)
|
160
|
+
}.should raise_error(ArgumentError)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'when unknown options use something that is not a Query::Operator, Symbol or String is a key' do
|
165
|
+
lambda {
|
166
|
+
DataMapper::Query.new(@repository, Article, nil => nil)
|
167
|
+
}.should raise_error(ArgumentError)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe 'should normalize' do
|
172
|
+
it '#fields' do
|
173
|
+
DataMapper::Query.new(@repository, Article, :fields => [:id]).fields.should == Article.properties.slice(:id)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'should translate custom types' do
|
178
|
+
before(:each) do
|
179
|
+
class Acl
|
180
|
+
include DataMapper::Resource
|
181
|
+
property :id, Integer
|
182
|
+
property :is_custom_type, DM::Boolean
|
183
|
+
end
|
184
|
+
end
|
185
|
+
it "should call Boolean#dump for :is_custom_type options" do
|
186
|
+
DM::Boolean.should_receive(:dump).with(:false, Acl.properties[:is_custom_type])
|
187
|
+
DataMapper::Query.new(@repository, Acl, :is_custom_type => :false)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should provide #update' do
|
193
|
+
@query.should respond_to(:update)
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '#update' do
|
197
|
+
before do
|
198
|
+
@query = DataMapper::Query.new(@repository, Article, UPDATED_OPTIONS)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should instantiate a DataMapper::Query object from other when it is a Hash' do
|
202
|
+
other = { :reload => :true }
|
203
|
+
|
204
|
+
@query.should_receive(:class).with(no_args).exactly(3).times.ordered.and_return(DataMapper::Query)
|
205
|
+
DataMapper::Query.should_receive(:new).with(@repository, @query.model, other).ordered.and_return(@query)
|
206
|
+
|
207
|
+
@query.update(other)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should raise an ArgumentError if other query model is different' do
|
211
|
+
lambda {
|
212
|
+
other = DataMapper::Query.new(@repository, Comment)
|
213
|
+
@query.update(other)
|
214
|
+
}.should raise_error(ArgumentError)
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should return self' do
|
218
|
+
other = DataMapper::Query.new(@repository, Article)
|
219
|
+
@query.update(other).should == @query
|
220
|
+
end
|
221
|
+
|
222
|
+
describe 'should overwrite the attribute' do
|
223
|
+
it '#reload? with other reload?' do
|
224
|
+
other = DataMapper::Query.new(@repository, Article, :reload => true)
|
225
|
+
@query.update(other).reload?.should == true
|
226
|
+
end
|
227
|
+
|
228
|
+
it '#offset with other offset when it is not equal to 0' do
|
229
|
+
other = DataMapper::Query.new(@repository, Article, :offset => 1)
|
230
|
+
@query.update(other).offset.should == 1
|
231
|
+
end
|
232
|
+
|
233
|
+
it '#limit with other limit when it is not nil' do
|
234
|
+
other = DataMapper::Query.new(@repository, Article, :limit => 1)
|
235
|
+
@query.update(other).limit.should == 1
|
236
|
+
end
|
237
|
+
|
238
|
+
it '#the operator if condition is the same and operater is changed (:not / :eql)' do
|
239
|
+
# especially needed for collection#update where you might do something like:
|
240
|
+
# all(:name.not => "John").update(:name => "John")
|
241
|
+
pending do
|
242
|
+
other = DataMapper::Query.new(@repository, Article, :author.not => "dkubb")
|
243
|
+
@query.update(other).conditions.should == [ [ :not, Article.properties[:author], 'dkubb' ] ]
|
244
|
+
@query.update(:author => "dkubb").conditions.should == [ [ :eql, Article.properties[:author], 'dkubb' ] ]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
[ :eql, :like ].each do |operator|
|
249
|
+
it "#conditions with other conditions when updating the '#{operator}' clause to a different value than in self" do
|
250
|
+
# set the initial conditions
|
251
|
+
@query.update(:author.send(operator) => 'ssmoot')
|
252
|
+
|
253
|
+
# update the conditions, and overwrite with the new value
|
254
|
+
other = DataMapper::Query.new(@repository, Article, :author.send(operator) => 'dkubb')
|
255
|
+
@query.update(other).conditions.should == [ [ operator, Article.properties[:author], 'dkubb' ] ]
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
[ :gt, :gte ].each do |operator|
|
260
|
+
it "#conditions with other conditions when updating the '#{operator}' clause to a value less than in self" do
|
261
|
+
# set the initial conditions
|
262
|
+
@query.update(:created_at.send(operator) => Time.at(1))
|
263
|
+
|
264
|
+
# update the conditions, and overwrite with the new value is less
|
265
|
+
other = DataMapper::Query.new(@repository, Article, :created_at.send(operator) => Time.at(0))
|
266
|
+
@query.update(other).conditions.should == [ [ operator, Article.properties[:created_at], Time.at(0) ] ]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
[ :lt, :lte ].each do |operator|
|
271
|
+
it "#conditions with other conditions when updating the '#{operator}' clause to a value greater than in self" do
|
272
|
+
# set the initial conditions
|
273
|
+
@query.update(:created_at.send(operator) => Time.at(0))
|
274
|
+
|
275
|
+
# update the conditions, and overwrite with the new value is more
|
276
|
+
other = DataMapper::Query.new(@repository, Article, :created_at.send(operator) => Time.at(1))
|
277
|
+
@query.update(other).conditions.should == [ [ operator, Article.properties[:created_at], Time.at(1) ] ]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
it "#order with other order unique values" do
|
282
|
+
order = [
|
283
|
+
DataMapper::Query::Direction.new(Article.properties[:created_at], :desc),
|
284
|
+
DataMapper::Query::Direction.new(Article.properties[:author], :desc),
|
285
|
+
DataMapper::Query::Direction.new(Article.properties[:title], :desc),
|
286
|
+
]
|
287
|
+
|
288
|
+
other = DataMapper::Query.new(@repository, Article, :order => order)
|
289
|
+
@query.update(other).order.should == order
|
290
|
+
end
|
291
|
+
|
292
|
+
# dkubb: I am not sure i understand the intent here. link now needs to be
|
293
|
+
# a DM::Assoc::Relationship or the name (Symbol or String) of an
|
294
|
+
# association on the Resource -- thx guyvdb
|
295
|
+
#
|
296
|
+
# NOTE: I have commented out :links in the GOOD_OPTIONS above
|
297
|
+
#
|
298
|
+
[ :links, :includes ].each do |attribute|
|
299
|
+
it "##{attribute} with other #{attribute} unique values" do
|
300
|
+
pending 'DataMapper::Query::Path not ready'
|
301
|
+
other = DataMapper::Query.new(@repository, Article, attribute => [ :stub, :other, :new ])
|
302
|
+
@query.update(other).send(attribute).should == [ :stub, :other, :new ]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
it "#fields with other fields unique values" do
|
307
|
+
other = DataMapper::Query.new(@repository, Article, :fields => [ :blog_id ])
|
308
|
+
@query.update(other).fields.should == Article.properties.slice(:blog_id)
|
309
|
+
end
|
310
|
+
|
311
|
+
it '#conditions with other conditions when they are unique' do
|
312
|
+
# set the initial conditions
|
313
|
+
@query.update(:title => 'On DataMapper')
|
314
|
+
|
315
|
+
# update the conditions, but merge the conditions together
|
316
|
+
other = DataMapper::Query.new(@repository, Article, :author => 'dkubb')
|
317
|
+
@query.update(other).conditions.should == [ [ :eql, Article.properties[:title], 'On DataMapper' ], [ :eql, Article.properties[:author], 'dkubb' ] ]
|
318
|
+
end
|
319
|
+
|
320
|
+
[ :not, :in ].each do |operator|
|
321
|
+
it "#conditions with other conditions when updating the '#{operator}' clause" do
|
322
|
+
# set the initial conditions
|
323
|
+
@query.update(:created_at.send(operator) => [ Time.at(0) ])
|
324
|
+
|
325
|
+
# update the conditions, and overwrite with the new value is more
|
326
|
+
other = DataMapper::Query.new(@repository, Article, :created_at.send(operator) => [ Time.at(1) ])
|
327
|
+
@query.update(other).conditions.should == [ [ operator, Article.properties[:created_at], [ Time.at(0), Time.at(1) ] ] ]
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
it '#conditions with other conditions when they have a one element condition' do
|
332
|
+
# set the initial conditions
|
333
|
+
@query.update(:title => 'On DataMapper')
|
334
|
+
|
335
|
+
# update the conditions, but merge the conditions together
|
336
|
+
other = DataMapper::Query.new(@repository, Article, :conditions => [ 'author = "dkubb"' ])
|
337
|
+
@query.update(other).conditions.should == [ [ :eql, Article.properties[:title], 'On DataMapper' ], [ :raw, 'author = "dkubb"' ] ]
|
338
|
+
end
|
339
|
+
|
340
|
+
it '#conditions with other conditions when they have a two or more element condition' do
|
341
|
+
# set the initial conditions
|
342
|
+
@query.update(:title => 'On DataMapper')
|
343
|
+
|
344
|
+
# update the conditions, but merge the conditions together
|
345
|
+
other = DataMapper::Query.new(@repository, Article, :conditions => [ 'author = ?', 'dkubb' ])
|
346
|
+
@query.update(other).conditions.should == [ [ :eql, Article.properties[:title], 'On DataMapper' ], [ :raw, 'author = ?', [ 'dkubb' ] ] ]
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
describe 'should not update the attribute' do
|
351
|
+
it '#offset when other offset is equal to 0' do
|
352
|
+
other = DataMapper::Query.new(@repository, Article, :offset => 0)
|
353
|
+
other.offset.should == 0
|
354
|
+
@query.update(other).offset.should == 1
|
355
|
+
end
|
356
|
+
|
357
|
+
it '#limit when other limit is nil' do
|
358
|
+
other = DataMapper::Query.new(@repository, Article)
|
359
|
+
other.limit.should be_nil
|
360
|
+
@query.update(other).offset.should == 1
|
361
|
+
end
|
362
|
+
|
363
|
+
[ :gt, :gte ].each do |operator|
|
364
|
+
it "#conditions with other conditions when they have a '#{operator}' clause with a value greater than in self" do
|
365
|
+
# set the initial conditions
|
366
|
+
@query.update(:created_at.send(operator) => Time.at(0))
|
367
|
+
|
368
|
+
# do not overwrite with the new value if it is more
|
369
|
+
other = DataMapper::Query.new(@repository, Article, :created_at.send(operator) => Time.at(1))
|
370
|
+
@query.update(other).conditions.should == [ [ operator, Article.properties[:created_at], Time.at(0) ] ]
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
[ :lt, :lte ].each do |operator|
|
375
|
+
it "#conditions with other conditions when they have a '#{operator}' clause with a value less than in self" do
|
376
|
+
# set the initial conditions
|
377
|
+
@query.update(:created_at.send(operator) => Time.at(1))
|
378
|
+
|
379
|
+
# do not overwrite with the new value if it is less
|
380
|
+
other = DataMapper::Query.new(@repository, Article, :created_at.send(operator) => Time.at(0))
|
381
|
+
@query.update(other).conditions.should == [ [ operator, Article.properties[:created_at], Time.at(1) ] ]
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'should provide #merge' do
|
388
|
+
@query.should respond_to(:merge)
|
389
|
+
end
|
390
|
+
|
391
|
+
describe '#merge' do
|
392
|
+
it 'should pass arguments as-is to duplicate object\'s #update method' do
|
393
|
+
dupe_query = @query.dup
|
394
|
+
@query.should_receive(:dup).with(no_args).ordered.and_return(dupe_query)
|
395
|
+
dupe_query.should_receive(:update).with(:author => 'dkubb').ordered
|
396
|
+
@query.merge(:author => 'dkubb')
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'should return the duplicate object' do
|
400
|
+
dupe_query = @query.merge(:author => 'dkubb')
|
401
|
+
@query.object_id.should_not == dupe_query.object_id
|
402
|
+
@query.merge(:author => 'dkubb').should == dupe_query
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'should provide #==' do
|
407
|
+
@query.should respond_to(:==)
|
408
|
+
end
|
409
|
+
|
410
|
+
describe '#==' do
|
411
|
+
describe 'should be equal' do
|
412
|
+
it 'when other is same object' do
|
413
|
+
@query.update(:author => 'dkubb').should == @query
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'when other has the same attributes' do
|
417
|
+
other = DataMapper::Query.new(@repository, Article)
|
418
|
+
@query.object_id.should_not == other.object_id
|
419
|
+
@query.should == other
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'when other has the same conditions sorted differently' do
|
423
|
+
@query.update(:author => 'dkubb')
|
424
|
+
@query.update(:title => 'On DataMapper')
|
425
|
+
|
426
|
+
other = DataMapper::Query.new(@repository, Article, :title => 'On DataMapper')
|
427
|
+
other.update(:author => 'dkubb')
|
428
|
+
|
429
|
+
# query conditions are in different order
|
430
|
+
@query.conditions.should == [ [ :eql, Article.properties[:author], 'dkubb' ], [ :eql, Article.properties[:title], 'On DataMapper' ] ]
|
431
|
+
other.conditions.should == [ [ :eql, Article.properties[:title], 'On DataMapper' ], [ :eql, Article.properties[:author], 'dkubb' ] ]
|
432
|
+
|
433
|
+
@query.should == other
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
describe 'should be different' do
|
438
|
+
it 'when other model is different than self.model' do
|
439
|
+
@query.should_not == DataMapper::Query.new(@repository, Comment)
|
440
|
+
end
|
441
|
+
|
442
|
+
UPDATED_OPTIONS.each do |attribute,value|
|
443
|
+
it "when other #{attribute} is different than self.#{attribute}" do
|
444
|
+
@query.should_not == DataMapper::Query.new(@repository, Article, attribute => value)
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
it 'when other conditions are different than self.conditions' do
|
449
|
+
@query.should_not == DataMapper::Query.new(@repository, Article, :author => 'dkubb')
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
it 'should provide #reverse' do
|
455
|
+
@query.should respond_to(:reverse)
|
456
|
+
end
|
457
|
+
|
458
|
+
describe '#reverse' do
|
459
|
+
it 'should create a duplicate query and delegate to #reverse!' do
|
460
|
+
copy = @query.dup
|
461
|
+
copy.should_receive(:reverse!).with(no_args).and_return(@query)
|
462
|
+
@query.should_receive(:dup).with(no_args).and_return(copy)
|
463
|
+
|
464
|
+
@query.reverse.should == @query
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'should provide #reverse!' do
|
469
|
+
@query.should respond_to(:reverse!)
|
470
|
+
end
|
471
|
+
|
472
|
+
describe '#reverse!' do
|
473
|
+
it 'should update the query with the reverse order' do
|
474
|
+
normal_order = Article.key.map { |p| DataMapper::Query::Direction.new(p, :asc) }
|
475
|
+
reverse_order = Article.key.map { |p| DataMapper::Query::Direction.new(p, :desc) }
|
476
|
+
|
477
|
+
normal_order.should_not be_empty
|
478
|
+
reverse_order.should_not be_empty
|
479
|
+
|
480
|
+
@query.order.should == normal_order
|
481
|
+
@query.should_receive(:update).with(:order => reverse_order)
|
482
|
+
@query.reverse!.object_id.should == @query.object_id
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
describe DataMapper::Query::Operator do
|
488
|
+
before do
|
489
|
+
@operator = :thing.gte
|
490
|
+
end
|
491
|
+
|
492
|
+
it 'should provide #==' do
|
493
|
+
@operator.should respond_to(:==)
|
494
|
+
end
|
495
|
+
|
496
|
+
describe '#==' do
|
497
|
+
describe 'should be equal' do
|
498
|
+
it 'when other is same object' do
|
499
|
+
@operator.should == @operator
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'when other has the same target and operator' do
|
503
|
+
other = :thing.gte
|
504
|
+
@operator.target.should == other.target
|
505
|
+
@operator.operator.should == other.operator
|
506
|
+
@operator.should == other
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
describe 'should be different' do
|
511
|
+
it 'when other class is not a descendant of self.class' do
|
512
|
+
other = :thing
|
513
|
+
other.class.should_not be_kind_of(@operator.class)
|
514
|
+
@operator.should_not == other
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'when other has a different target' do
|
518
|
+
other = :other.gte
|
519
|
+
@operator.target.should_not == other.target
|
520
|
+
@operator.should_not == other
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'when other has a different operator' do
|
524
|
+
other = :thing.gt
|
525
|
+
@operator.operator.should_not == other.operator
|
526
|
+
@operator.should_not == other
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|