friendly_postgres 0.4.3
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/.document +2 -0
- data/.gitignore +26 -0
- data/APACHE-LICENSE +202 -0
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTORS.md +7 -0
- data/LICENSE +20 -0
- data/README.md +265 -0
- data/Rakefile +68 -0
- data/TODO.md +5 -0
- data/VERSION +1 -0
- data/examples/friendly.yml +7 -0
- data/friendly.gemspec +232 -0
- data/lib/friendly.rb +54 -0
- data/lib/friendly/associations.rb +7 -0
- data/lib/friendly/associations/association.rb +34 -0
- data/lib/friendly/associations/set.rb +37 -0
- data/lib/friendly/attribute.rb +91 -0
- data/lib/friendly/boolean.rb +10 -0
- data/lib/friendly/cache.rb +24 -0
- data/lib/friendly/cache/by_id.rb +33 -0
- data/lib/friendly/config.rb +5 -0
- data/lib/friendly/data_store.rb +72 -0
- data/lib/friendly/document.rb +257 -0
- data/lib/friendly/document_table.rb +56 -0
- data/lib/friendly/index.rb +73 -0
- data/lib/friendly/memcached.rb +48 -0
- data/lib/friendly/named_scope.rb +17 -0
- data/lib/friendly/newrelic.rb +6 -0
- data/lib/friendly/query.rb +42 -0
- data/lib/friendly/scope.rb +100 -0
- data/lib/friendly/scope_proxy.rb +45 -0
- data/lib/friendly/sequel_monkey_patches.rb +34 -0
- data/lib/friendly/storage.rb +31 -0
- data/lib/friendly/storage_factory.rb +24 -0
- data/lib/friendly/storage_proxy.rb +103 -0
- data/lib/friendly/table.rb +15 -0
- data/lib/friendly/table_creator.rb +48 -0
- data/lib/friendly/time.rb +14 -0
- data/lib/friendly/translator.rb +32 -0
- data/lib/friendly/uuid.rb +148 -0
- data/rails/init.rb +3 -0
- data/spec/config.yml.example +7 -0
- data/spec/fakes/data_store_fake.rb +29 -0
- data/spec/fakes/database_fake.rb +12 -0
- data/spec/fakes/dataset_fake.rb +28 -0
- data/spec/fakes/document.rb +18 -0
- data/spec/fakes/serializer_fake.rb +12 -0
- data/spec/fakes/time_fake.rb +12 -0
- data/spec/integration/ad_hoc_scopes_spec.rb +42 -0
- data/spec/integration/basic_object_lifecycle_spec.rb +114 -0
- data/spec/integration/batch_insertion_spec.rb +29 -0
- data/spec/integration/convenience_api_spec.rb +25 -0
- data/spec/integration/count_spec.rb +12 -0
- data/spec/integration/default_value_spec.rb +15 -0
- data/spec/integration/find_via_cache_spec.rb +101 -0
- data/spec/integration/finder_spec.rb +64 -0
- data/spec/integration/has_many_spec.rb +18 -0
- data/spec/integration/index_spec.rb +57 -0
- data/spec/integration/named_scope_spec.rb +34 -0
- data/spec/integration/pagination_spec.rb +63 -0
- data/spec/integration/scope_chaining_spec.rb +22 -0
- data/spec/integration/table_creator_spec.rb +64 -0
- data/spec/integration/write_through_cache_spec.rb +53 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/unit/associations/association_spec.rb +57 -0
- data/spec/unit/associations/set_spec.rb +43 -0
- data/spec/unit/attribute_spec.rb +105 -0
- data/spec/unit/cache_by_id_spec.rb +102 -0
- data/spec/unit/cache_spec.rb +21 -0
- data/spec/unit/config_spec.rb +4 -0
- data/spec/unit/data_store_spec.rb +188 -0
- data/spec/unit/document_spec.rb +358 -0
- data/spec/unit/document_table_spec.rb +126 -0
- data/spec/unit/friendly_spec.rb +25 -0
- data/spec/unit/index_spec.rb +196 -0
- data/spec/unit/memcached_spec.rb +114 -0
- data/spec/unit/named_scope_spec.rb +16 -0
- data/spec/unit/query_spec.rb +104 -0
- data/spec/unit/scope_proxy_spec.rb +44 -0
- data/spec/unit/scope_spec.rb +113 -0
- data/spec/unit/storage_factory_spec.rb +59 -0
- data/spec/unit/storage_proxy_spec.rb +218 -0
- data/spec/unit/translator_spec.rb +96 -0
- data/website/index.html +210 -0
- data/website/scripts/clipboard.swf +0 -0
- data/website/scripts/shBrushAS3.js +61 -0
- data/website/scripts/shBrushBash.js +66 -0
- data/website/scripts/shBrushCSharp.js +67 -0
- data/website/scripts/shBrushColdFusion.js +102 -0
- data/website/scripts/shBrushCpp.js +99 -0
- data/website/scripts/shBrushCss.js +93 -0
- data/website/scripts/shBrushDelphi.js +57 -0
- data/website/scripts/shBrushDiff.js +43 -0
- data/website/scripts/shBrushErlang.js +54 -0
- data/website/scripts/shBrushGroovy.js +69 -0
- data/website/scripts/shBrushJScript.js +52 -0
- data/website/scripts/shBrushJava.js +59 -0
- data/website/scripts/shBrushJavaFX.js +60 -0
- data/website/scripts/shBrushPerl.js +74 -0
- data/website/scripts/shBrushPhp.js +91 -0
- data/website/scripts/shBrushPlain.js +35 -0
- data/website/scripts/shBrushPowerShell.js +76 -0
- data/website/scripts/shBrushPython.js +66 -0
- data/website/scripts/shBrushRuby.js +57 -0
- data/website/scripts/shBrushScala.js +53 -0
- data/website/scripts/shBrushSql.js +68 -0
- data/website/scripts/shBrushVb.js +58 -0
- data/website/scripts/shBrushXml.js +71 -0
- data/website/scripts/shCore.js +30 -0
- data/website/scripts/shLegacy.js +30 -0
- data/website/styles/friendly.css +103 -0
- data/website/styles/help.png +0 -0
- data/website/styles/ie.css +35 -0
- data/website/styles/magnifier.png +0 -0
- data/website/styles/page_white_code.png +0 -0
- data/website/styles/page_white_copy.png +0 -0
- data/website/styles/print.css +29 -0
- data/website/styles/printer.png +0 -0
- data/website/styles/screen.css +257 -0
- data/website/styles/shCore.css +330 -0
- data/website/styles/shThemeDefault.css +173 -0
- data/website/styles/shThemeDjango.css +176 -0
- data/website/styles/shThemeEclipse.css +190 -0
- data/website/styles/shThemeEmacs.css +175 -0
- data/website/styles/shThemeFadeToGrey.css +177 -0
- data/website/styles/shThemeMidnight.css +175 -0
- data/website/styles/shThemeRDark.css +175 -0
- metadata +302 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::Document" do
|
|
4
|
+
before do
|
|
5
|
+
@klass = Class.new { include Friendly::Document }
|
|
6
|
+
@klass.attribute(:name, String)
|
|
7
|
+
@storage_proxy = stub
|
|
8
|
+
@klass.storage_proxy = @storage_proxy
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "delegates table_name to it's class" do
|
|
12
|
+
User.new.table_name.should == User.table_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "always has an id attribute" do
|
|
16
|
+
@klass.attributes[:id].type.should == Friendly::UUID
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "always has a created_at attribute" do
|
|
20
|
+
@klass.attributes[:created_at].type.should == Time
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "always has a updated_at attribute" do
|
|
24
|
+
@klass.attributes[:updated_at].type.should == Time
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "saving a new document" do
|
|
28
|
+
before do
|
|
29
|
+
@user = @klass.new(:name => "whatever")
|
|
30
|
+
@storage_proxy.stubs(:create)
|
|
31
|
+
@user.save
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "asks the storage_proxy to create" do
|
|
35
|
+
@storage_proxy.should have_received(:create).with(@user)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "saving an existing document" do
|
|
40
|
+
before do
|
|
41
|
+
@user = @klass.new(:name => "whatever", :id => 42, :new_record => false)
|
|
42
|
+
@storage_proxy.stubs(:update)
|
|
43
|
+
@user.save
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "asks the storage_proxy to update" do
|
|
47
|
+
@storage_proxy.should have_received(:update).with(@user)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "destroying a document" do
|
|
52
|
+
before do
|
|
53
|
+
@user = @klass.new
|
|
54
|
+
@storage_proxy.stubs(:destroy)
|
|
55
|
+
@user.destroy
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "delegates to the storage proxy" do
|
|
59
|
+
@storage_proxy.should have_received(:destroy).with(@user)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe "converting a document to a hash" do
|
|
64
|
+
before do
|
|
65
|
+
@object = @klass.new(:name => "Stewie")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "creates a hash that contains its attributes" do
|
|
69
|
+
@object.to_hash.should == {:name => "Stewie",
|
|
70
|
+
:id => @object.id,
|
|
71
|
+
:created_at => @object.created_at,
|
|
72
|
+
:updated_at => @object.updated_at}
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "setting the attributes all at once" do
|
|
77
|
+
before do
|
|
78
|
+
@object = @klass.new
|
|
79
|
+
@object.attributes = {:name => "Bond"}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "sets the attributes using the setters" do
|
|
83
|
+
@object.name.should == "Bond"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "raises ArgumentError when there are duplicate keys of differing type" do
|
|
87
|
+
lambda {
|
|
88
|
+
@object.attributes = {:name => "Bond", "name" => "Bond"}
|
|
89
|
+
}.should raise_error(ArgumentError)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe "initializing a document" do
|
|
94
|
+
before do
|
|
95
|
+
@doc = @klass.new :name => "Bond"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "sets the attributes using the setters" do
|
|
99
|
+
@doc.name.should == "Bond"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "table name" do
|
|
104
|
+
it "by default: is the class name, converted with pluralize.underscore" do
|
|
105
|
+
User.table_name.should == "users"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "is overridable" do
|
|
109
|
+
@klass.table_name = "ASDF"
|
|
110
|
+
@klass.table_name.should == "ASDF"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe "new record" do
|
|
115
|
+
before do
|
|
116
|
+
@object = @klass.new
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "is new_record by default" do
|
|
120
|
+
@object.should be_new_record
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "is not new_record when new_record is set to false" do
|
|
124
|
+
@object.new_record = false
|
|
125
|
+
@object.should_not be_new_record
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
describe "object equality" do
|
|
130
|
+
it "is never equal if both objects are new_records" do
|
|
131
|
+
@klass.new(:name => "x").should_not == @klass.new(:name => "x")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "is equal if both objects have the same id" do
|
|
135
|
+
uuid = Friendly::UUID.new
|
|
136
|
+
one = @klass.new(:id => uuid, :new_record => false)
|
|
137
|
+
one.should == @klass.new(:id => uuid, :new_record => false)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "is equal if the objects point to the same reference" do
|
|
141
|
+
obj = @klass.new
|
|
142
|
+
obj.should == obj
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "is not equal if two objects are of differing types with the same id" do
|
|
146
|
+
@klass.new(:id => 1).should_not == User.new(:id => 1)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe "adding an index" do
|
|
151
|
+
before do
|
|
152
|
+
@storage_proxy.stubs(:add)
|
|
153
|
+
@klass = Class.new { include Friendly::Document }
|
|
154
|
+
@klass.storage_proxy = @storage_proxy
|
|
155
|
+
@klass.indexes :name
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "delegates to the storage_proxy" do
|
|
159
|
+
@klass.storage_proxy.should have_received(:add).with([:name])
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
describe "adding a cache" do
|
|
164
|
+
before do
|
|
165
|
+
@storage_proxy.stubs(:cache)
|
|
166
|
+
@klass.caches_by(:name, :created_at)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "delegates to the storage_proxy" do
|
|
170
|
+
@storage_proxy.should have_received(:cache).with([:name, :created_at], {})
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe "Document.first" do
|
|
175
|
+
before do
|
|
176
|
+
@doc = stub
|
|
177
|
+
@query = stub
|
|
178
|
+
@query_klass = stub
|
|
179
|
+
@klass.query_klass = @query_klass
|
|
180
|
+
@query_klass.stubs(:new).with(:id => 1).returns(@query)
|
|
181
|
+
@storage_proxy.stubs(:first).with(@query).returns(@doc)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "creates a query object and delegates to the storage proxy" do
|
|
185
|
+
@klass.first(:id => 1).should == @doc
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
describe "Document.all" do
|
|
190
|
+
before do
|
|
191
|
+
@docs = stub
|
|
192
|
+
@query = stub
|
|
193
|
+
@query_klass = stub
|
|
194
|
+
@klass.query_klass = @query_klass
|
|
195
|
+
@query_klass.stubs(:new).with(:name => "x").returns(@query)
|
|
196
|
+
@storage_proxy.stubs(:all).with(@query).returns(@docs)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "delegates to the storage proxy" do
|
|
200
|
+
@klass.all(:name => "x").should == @docs
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
describe "Document.find" do
|
|
205
|
+
describe "when an object is found" do
|
|
206
|
+
before do
|
|
207
|
+
@doc = stub
|
|
208
|
+
@query = stub
|
|
209
|
+
@query_klass = stub
|
|
210
|
+
@klass.query_klass = @query_klass
|
|
211
|
+
@query_klass.stubs(:new).with(:id => 1).returns(@query)
|
|
212
|
+
@storage_proxy.stubs(:first).with(@query).returns(@doc)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "queries the storage proxy" do
|
|
216
|
+
@klass.find(1).should == @doc
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
describe "when no object is found" do
|
|
221
|
+
before do
|
|
222
|
+
@storage_proxy.stubs(:first).returns(nil)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "raises RecordNotFound" do
|
|
226
|
+
lambda {
|
|
227
|
+
@klass.find(1)
|
|
228
|
+
}.should raise_error(Friendly::RecordNotFound)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
describe "Document.all" do
|
|
234
|
+
before do
|
|
235
|
+
@query = stub
|
|
236
|
+
@query_klass = stub
|
|
237
|
+
@klass.query_klass = @query_klass
|
|
238
|
+
@query_klass.stubs(:new).with(:name => "x").returns(@query)
|
|
239
|
+
@storage_proxy.stubs(:count).with(@query).returns(25)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "delegates to the storage proxy" do
|
|
243
|
+
@klass.count(:name => "x").should == 25
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
describe "Document.create" do
|
|
248
|
+
before do
|
|
249
|
+
@storage_proxy.stubs(:create)
|
|
250
|
+
@doc = @klass.create(:name => "James")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it "initializes, then saves the document and returns it" do
|
|
254
|
+
@storage_proxy.should have_received(:create).with(@doc)
|
|
255
|
+
@doc.should be_kind_of(@klass)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
describe "Document#update_attributes" do
|
|
260
|
+
before do
|
|
261
|
+
@storage_proxy.stubs(:update)
|
|
262
|
+
@doc = @klass.new(:name => "James", :new_record => false)
|
|
263
|
+
@doc.update_attributes :name => "Steve"
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "sets the attributes" do
|
|
267
|
+
@doc.name.should == "Steve"
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it "saves the document" do
|
|
271
|
+
@storage_proxy.should have_received(:update).with(@doc)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
describe "when document has been included" do
|
|
276
|
+
after { Friendly::Document.documents = [] }
|
|
277
|
+
it "adds the document to the collection" do
|
|
278
|
+
Friendly::Document.documents.should include(@klass)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
describe "Document.paginate" do
|
|
283
|
+
before do
|
|
284
|
+
@conditions = {:name => "Stewie", :page! => 1, :per_page! => 20}
|
|
285
|
+
@query = stub(:page => 1, :per_page => 20)
|
|
286
|
+
@docs = stub
|
|
287
|
+
@query_klass = stub
|
|
288
|
+
@klass.query_klass = @query_klass
|
|
289
|
+
@count = 10
|
|
290
|
+
@collection_klass = stub
|
|
291
|
+
@collection = stub
|
|
292
|
+
@klass.collection_klass = @collection_klass
|
|
293
|
+
@collection.stubs(:replace).returns(@collection)
|
|
294
|
+
@collection_klass.stubs(:new).with(1, 20, @count).returns(@collection)
|
|
295
|
+
@query_klass.stubs(:new).returns(@query)
|
|
296
|
+
@storage_proxy.stubs(:count).with(@query).returns(@count)
|
|
297
|
+
@storage_proxy.stubs(:all).with(@query).returns(@docs)
|
|
298
|
+
|
|
299
|
+
@pagination = @klass.paginate(@conditions)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
it "creates an instance of the collection klass and returns it" do
|
|
303
|
+
@pagination.should == @collection
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it "fills the collection with objects from the datastore" do
|
|
307
|
+
@collection.should have_received(:replace).with(@docs)
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
describe "creating a named_scope" do
|
|
312
|
+
before do
|
|
313
|
+
@scope_proxy = stub(:add_named => nil)
|
|
314
|
+
@klass.scope_proxy = @scope_proxy
|
|
315
|
+
@klass.named_scope(:by_name, :order => :name)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "asks the named_scope_set to add it" do
|
|
319
|
+
@klass.scope_proxy.should have_received(:add_named).
|
|
320
|
+
with(:by_name, :order => :name)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
describe "Document.has_named_scope?" do
|
|
325
|
+
it "delegates to the scope_proxy" do
|
|
326
|
+
@scope_proxy = stub
|
|
327
|
+
@scope_proxy.stubs(:has_named_scope?).with(:whatever).returns(true)
|
|
328
|
+
@klass.scope_proxy = @scope_proxy
|
|
329
|
+
@klass.has_named_scope?(:whatever).should be_true
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
describe "accessing an ad-hoc scope" do
|
|
334
|
+
before do
|
|
335
|
+
@scope = stub
|
|
336
|
+
@scope_proxy = stub
|
|
337
|
+
@scope_proxy.stubs(:ad_hoc).with(:order! => :name).returns(@scope)
|
|
338
|
+
@klass.scope_proxy = @scope_proxy
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it "asks the named_scope_set to add it" do
|
|
342
|
+
@klass.scope(:order! => :name).should == @scope
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
describe "adding an association" do
|
|
347
|
+
before do
|
|
348
|
+
@assoc_set = stub(:add => nil)
|
|
349
|
+
@klass.association_set = @assoc_set
|
|
350
|
+
@klass.has_many :addresses
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it "asks the association set to add it" do
|
|
354
|
+
@assoc_set.should have_received(:add).with(:addresses, {})
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::DocumentTable" do
|
|
4
|
+
before do
|
|
5
|
+
@datastore = stub(:insert => 42, :update => nil, :delete => nil)
|
|
6
|
+
@klass = stub(:table_name => "users")
|
|
7
|
+
@translator = stub
|
|
8
|
+
@table = Friendly::DocumentTable.new(@klass, @datastore, @translator)
|
|
9
|
+
@subject = @table
|
|
10
|
+
@document = FakeDocument.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "has a table name of klass.table_name" do
|
|
14
|
+
@table.table_name.should == "users"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it { should be_satisfies(query(:id => 1)) }
|
|
18
|
+
it { should_not be_satisfies(query(:id => 1, :name => "x")) }
|
|
19
|
+
it { should_not be_satisfies(query(:name => "x")) }
|
|
20
|
+
it { should_not be_satisfies(query(:id => 1, :order! => :created_at.desc)) }
|
|
21
|
+
|
|
22
|
+
describe "saving an object" do
|
|
23
|
+
before do
|
|
24
|
+
@document_hash = {:name => "whatever"}
|
|
25
|
+
@document = FakeDocument.new :table_name => "users",
|
|
26
|
+
:to_hash => @document_hash
|
|
27
|
+
@record = {:created_at => Time.new, :updated_at => Time.new}
|
|
28
|
+
@translator.stubs(:to_record).with(@document).returns(@record)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "when it is a new_record?" do
|
|
32
|
+
before do
|
|
33
|
+
@document.new_record = true
|
|
34
|
+
@table.create(@document)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "saves the record from the translator to the database" do
|
|
38
|
+
@datastore.should have_received(:insert).with(@document, @record)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "sets the created_at on the document" do
|
|
42
|
+
@document.created_at.should == @record[:created_at]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "sets the updated_at on the document" do
|
|
46
|
+
@document.updated_at.should == @record[:updated_at]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "sets new_record to false" do
|
|
50
|
+
@document.should_not be_new_record
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "updating a record" do
|
|
55
|
+
before do
|
|
56
|
+
@document.id = 24
|
|
57
|
+
@document.new_record = false
|
|
58
|
+
@table.update(@document)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "saves the record from the translator" do
|
|
62
|
+
@datastore.should have_received(:update).with(@document, 24, @record)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "sets the created_at from the translator" do
|
|
66
|
+
@document.created_at.should == @record[:created_at]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "sets the updated_at from the translator" do
|
|
70
|
+
@document.updated_at.should == @record[:updated_at]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe "destroying an object" do
|
|
76
|
+
before do
|
|
77
|
+
@document.id = 42
|
|
78
|
+
@table.destroy(@document)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "asks the datastore to delete" do
|
|
82
|
+
@datastore.should have_received(:delete).with(@document, 42)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe "finding the first object" do
|
|
87
|
+
describe "when the object is found" do
|
|
88
|
+
before do
|
|
89
|
+
@record = {:id => 1}
|
|
90
|
+
@document = stub
|
|
91
|
+
@datastore.stubs(:first).with(@klass, :id => 1).returns(@record)
|
|
92
|
+
@translator.stubs(:to_object).with(@klass, @record).returns(@document)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "queries the datastore and translates the object" do
|
|
96
|
+
@table.first(:id => 1).should == @document
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe "when the object is not found" do
|
|
101
|
+
before do
|
|
102
|
+
@datastore.stubs(:first).with(@klass, :id => 1).returns(nil)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "returns nil" do
|
|
106
|
+
@table.first(:id => 1).should be_nil
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe "finding many objects" do
|
|
112
|
+
before do
|
|
113
|
+
@records = [row(:id => 1), row(:id => 2)]
|
|
114
|
+
@document = stub
|
|
115
|
+
@query = query(:id => [1,2])
|
|
116
|
+
@records.each do |r|
|
|
117
|
+
@translator.stubs(:to_object).with(@klass, r).returns(@document).once
|
|
118
|
+
end
|
|
119
|
+
@datastore.stubs(:all).with(@klass, @query).returns(@records)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "queries the datastore and translates the returned records" do
|
|
123
|
+
@table.all(@query).should == [@document, @document]
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|