aqua 0.1.6 → 0.2.0
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/.gitignore +2 -1
- data/Aqua.gemspec +14 -11
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/aqua.rb +5 -7
- data/lib/aqua/object/config.rb +2 -3
- data/lib/aqua/object/initializers.rb +309 -0
- data/lib/aqua/object/pack.rb +56 -132
- data/lib/aqua/object/query.rb +30 -2
- data/lib/aqua/object/stub.rb +60 -95
- data/lib/aqua/object/tank.rb +1 -0
- data/lib/aqua/object/translator.rb +313 -0
- data/lib/aqua/object/unpack.rb +26 -227
- data/lib/aqua/store/couch_db/couch_db.rb +1 -0
- data/lib/aqua/store/couch_db/database.rb +1 -1
- data/lib/aqua/store/couch_db/design_document.rb +126 -2
- data/lib/aqua/store/couch_db/result_set.rb +36 -0
- data/lib/aqua/store/couch_db/storage_methods.rb +182 -17
- data/lib/aqua/store/storage.rb +4 -48
- data/lib/aqua/support/mash.rb +2 -3
- data/lib/aqua/support/set.rb +4 -16
- data/spec/object/object_fixtures/array_udder.rb +1 -1
- data/spec/object/object_fixtures/persistent.rb +0 -2
- data/spec/object/pack_spec.rb +137 -517
- data/spec/object/query_spec.rb +36 -6
- data/spec/object/stub_spec.rb +10 -9
- data/spec/object/translator_packing_spec.rb +402 -0
- data/spec/object/translator_unpacking_spec.rb +262 -0
- data/spec/object/unpack_spec.rb +162 -320
- data/spec/spec_helper.rb +18 -0
- data/spec/store/couchdb/design_document_spec.rb +148 -7
- data/spec/store/couchdb/result_set_spec.rb +95 -0
- data/spec/store/couchdb/storage_methods_spec.rb +150 -10
- metadata +13 -9
- data/lib/aqua/support/initializers.rb +0 -216
- data/spec/object/object_fixtures/grounded.rb +0 -13
- data/spec/object/object_fixtures/sugar.rb +0 -4
data/lib/aqua/support/mash.rb
CHANGED
@@ -137,8 +137,7 @@ unless defined?(HashWithIndifferentAccess)
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
140
|
-
|
141
|
-
Mash = HashWithIndifferentAccess unless defined?( Mash ) # because Mash is easier to write, thanks Merb!
|
142
|
-
|
143
140
|
end
|
141
|
+
|
142
|
+
Mash = HashWithIndifferentAccess unless defined?( Mash ) # because Mash is easier to write, thanks Merb!
|
144
143
|
|
data/lib/aqua/support/set.rb
CHANGED
@@ -2,22 +2,10 @@
|
|
2
2
|
require 'set'
|
3
3
|
|
4
4
|
class Set
|
5
|
-
include Aqua::Initializers
|
5
|
+
include Aqua::Initializers
|
6
|
+
hide_attributes :hash
|
6
7
|
|
7
|
-
def
|
8
|
-
hash
|
9
|
-
'class' => self.class.to_s,
|
10
|
-
'init' => to_aqua_init( base_object )
|
11
|
-
}
|
12
|
-
if (instance_variables - ['@hash']).size > 0
|
13
|
-
hash.merge!({ 'ivars' => base_object._pack_ivars( self ) })
|
14
|
-
end
|
15
|
-
hash
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_aqua_init( base_object )
|
19
|
-
# keys returns an array
|
20
|
-
# to_aqua_init will ensure that each of the objects is unpacked to aqua
|
21
|
-
instance_variable_get("@hash").keys.to_aqua_init( base_object )
|
8
|
+
def to_aqua_init( path='' )
|
9
|
+
Aqua::Translator.pack_object( instance_variable_get("@hash").keys )
|
22
10
|
end
|
23
11
|
end
|
data/spec/object/pack_spec.rb
CHANGED
@@ -5,129 +5,22 @@ Aqua.set_storage_engine('CouchDB') # to initialize CouchDB
|
|
5
5
|
CouchDB = Aqua::Store::CouchDB unless defined?( CouchDB )
|
6
6
|
|
7
7
|
describe Aqua::Pack do
|
8
|
-
before(:each) do
|
9
|
-
@time = Time.now
|
10
|
-
@date = Date.parse('12/23/1969')
|
11
|
-
@log = Log.new( :message => "Hello World! This is a log entry", :created_at => Time.now )
|
12
|
-
@user = User.new(
|
13
|
-
:username => 'kane',
|
14
|
-
:name => ['Kane', 'Baccigalupi'],
|
15
|
-
:dob => @date,
|
16
|
-
:created_at => @time,
|
17
|
-
:log => @log,
|
18
|
-
:password => 'my secret!'
|
19
|
-
)
|
20
|
-
|
21
|
-
def pack_grab_bag( value )
|
22
|
-
@user.grab_bag = value
|
23
|
-
@user._pack[:ivars][:@grab_bag]
|
24
|
-
end
|
25
|
-
end
|
26
8
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
9
|
+
def pack_grab_bag( value )
|
10
|
+
@user.grab_bag = value
|
11
|
+
@user._pack[:ivars][:@grab_bag]
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'translator' do
|
15
|
+
# the translator packs the object
|
16
|
+
# then the translator passes back the attachments and the externals back to the pack/storage document
|
17
|
+
end
|
35
18
|
|
36
|
-
describe '
|
19
|
+
describe 'hiding attributes' do
|
37
20
|
before(:each) do
|
38
|
-
|
39
|
-
|
40
|
-
@user.other_user = @graeme
|
41
|
-
@pack = @user._pack
|
42
|
-
end
|
43
|
-
|
44
|
-
describe 'packing' do
|
45
|
-
it 'should pack a stubbed object representation under __pack[:stubs]' do
|
46
|
-
@pack[:stubs].size.should == 1
|
47
|
-
other_user_pack = @pack[:stubs].first
|
48
|
-
other_user_pack[:class].should == "User"
|
49
|
-
other_user_pack[:id].should == @graeme
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should pack the values of a stubbed methods' do
|
53
|
-
other_user_pack = @pack[:stubs].first
|
54
|
-
other_user_pack[:methods].size.should == 1
|
55
|
-
other_user_pack[:methods][:username].should == 'graeme'
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should pack a stub of an object with embed=>false" do
|
59
|
-
sugar = Sugar.new
|
60
|
-
sugar.sweetness = Sugar.new
|
61
|
-
lambda {sugar._pack}.should_not raise_error
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should pack an array of stubbed methods' do
|
65
|
-
User.configure_aqua( :embed => {:stub => [:username, :name] } )
|
66
|
-
@user = User.new(
|
67
|
-
:username => 'kane',
|
68
|
-
:name => ['Kane', 'Baccigalupi'],
|
69
|
-
:dob => @date,
|
70
|
-
:created_at => @time,
|
71
|
-
:log => @log,
|
72
|
-
:password => 'my secret!',
|
73
|
-
:other_user => @graeme
|
74
|
-
)
|
75
|
-
|
76
|
-
@pack = @user._pack
|
77
|
-
other_user_pack = @pack[:stubs].first
|
78
|
-
other_user_pack[:methods].size.should == 2
|
79
|
-
other_user_pack[:methods][:username].should == 'graeme'
|
80
|
-
other_user_pack[:methods][:name].should == ['Graeme', 'Nelson']
|
81
|
-
|
82
|
-
# reseting the User model, and @user instance
|
83
|
-
User.configure_aqua( :embed => {:stub => :username } )
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'should pack the object itself with the class "Aqua::Stub"' do
|
87
|
-
@pack[:ivars][:@other_user][:class].should == "Aqua::Stub"
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'should pack the object itself with a reference to the __pack[:stubs] object' do
|
91
|
-
@pack[:ivars][:@other_user][:init].should == "/STUB_0"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe 'commiting' do
|
96
|
-
it 'should commit external objects' do
|
97
|
-
@user.commit!
|
98
|
-
db_docs = CouchDB::Database.new.documents
|
99
|
-
db_docs['total_rows'].should == 2
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'should save the id to the stub after commiting' do
|
103
|
-
@user.commit!
|
104
|
-
doc = CouchDB.get( "http://127.0.0.1:5984/aqua/#{@user.id}" )
|
105
|
-
doc["stubs"].first["id"].class.should == String
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'should log a warning if an external object doesn\'t commit' do
|
109
|
-
@graeme.should_receive(:commit).and_return(false)
|
110
|
-
@user.commit!
|
111
|
-
@user._warnings.size.should == 1
|
112
|
-
@user._warnings.first.should match(/unable to save/i)
|
113
|
-
end
|
21
|
+
build_user_ivars
|
22
|
+
end
|
114
23
|
|
115
|
-
it 'should log a warning and save the id if an object has an id' do
|
116
|
-
@graeme.commit!
|
117
|
-
@graeme.should_receive(:commit).and_return(false)
|
118
|
-
@user.commit!
|
119
|
-
@user._warnings.size.should == 1
|
120
|
-
@user._warnings.first.should match(/unable to save latest/i)
|
121
|
-
doc = CouchDB.get( "http://127.0.0.1:5984/aqua/#{@user.id}" )
|
122
|
-
doc["stubs"].first["id"].class.should == String
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'should rollback external commits if the parent object doesn\'t save'
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
describe 'hiding attributes' do
|
131
24
|
it 'should add a class method for designating hidden instance variables' do
|
132
25
|
User.should respond_to( :hide_attributes )
|
133
26
|
end
|
@@ -148,417 +41,140 @@ describe Aqua::Pack do
|
|
148
41
|
end
|
149
42
|
|
150
43
|
it 'should not pack hidden variables' do
|
151
|
-
|
152
|
-
|
44
|
+
pack = @user._pack
|
45
|
+
pack[:ivars].keys.should_not include("@password")
|
153
46
|
end
|
154
|
-
end
|
47
|
+
end
|
155
48
|
|
156
|
-
describe '
|
157
|
-
before(:each) do
|
158
|
-
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'should save its class name as an attribute on the pack document' do
|
162
|
-
@pack[:class].should == 'User'
|
49
|
+
describe 'embed/stub reporting' do
|
50
|
+
before(:each) do
|
51
|
+
build_user_ivars
|
163
52
|
end
|
164
|
-
|
165
|
-
|
166
|
-
|
53
|
+
|
54
|
+
describe '_embedded?' do
|
55
|
+
it 'should be true for embedded objects' do
|
56
|
+
@log._embedded?.should == true
|
57
|
+
end
|
58
|
+
it 'should be false for stubbed object with methods' do
|
59
|
+
@user._embedded?.should == false
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should be false without stubbed methods, where :embed configuration is false' do
|
63
|
+
p = Persistent.new
|
64
|
+
p._embedded?.should == false
|
65
|
+
end
|
167
66
|
end
|
168
67
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
68
|
+
describe '_stubbed_methods' do
|
69
|
+
it 'should be an empty for embedded objects (with no possible stubbed methods)' do
|
70
|
+
@log._stubbed_methods.should == []
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should be an array the stub string or symbol method passed into configuration' do
|
74
|
+
@user._stubbed_methods.should == [:username]
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should be the array of the stub methods passed into configuration' do
|
78
|
+
User.configure_aqua :embed => { :stub => [:username, :name] }
|
79
|
+
@user._stubbed_methods.should == [:username, :name]
|
80
|
+
User.configure_aqua :embed => { :stub => :username } # resetting user model
|
81
|
+
end
|
173
82
|
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
# Most of the serious packing tests are in packer_spec
|
87
|
+
# This is just to test/double-check that everything is working right withing an aquatic object
|
88
|
+
describe "nesting" do
|
89
|
+
before(:each) do
|
90
|
+
build_user_ivars
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'embedded aquatics' do
|
94
|
+
it 'should pack an embedded object internally' do
|
95
|
+
@pack[:ivars]['@log'].should == {
|
96
|
+
'class' => 'Log',
|
97
|
+
'ivars' => {'@message' => @message, '@created_at' => Aqua::Translator.pack_object( @time ).pack }
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
174
101
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
end
|
180
|
-
|
181
|
-
describe 'instance variables, ' do
|
182
|
-
describe 'hashes'
|
183
|
-
it 'should be in a hash-like object with the key :ivars' do
|
184
|
-
@pack[:ivars].should_not be_nil
|
185
|
-
@pack[:ivars].should respond_to(:keys)
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'should save symbol keys differently that string keys' do
|
189
|
-
@user.name = {:first => 'Kane', 'last' => 'Baccigalupi'}
|
190
|
-
pack = @user._pack
|
191
|
-
pack[:ivars][:@name][:init].keys.sort.should == [':first', 'last']
|
192
|
-
end
|
102
|
+
describe 'externals' do
|
103
|
+
before(:each) do
|
104
|
+
User::Storage.database.delete_all
|
105
|
+
end
|
193
106
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
it 'should pack an array of strings as a hash with the :class "Array" and :init as the original array' do
|
200
|
-
@pack[:ivars][:@name].should == {'class' => 'Array', 'init' => ['Kane', 'Baccigalupi']}
|
201
|
-
end
|
107
|
+
it 'should stub an external object' do
|
108
|
+
@pack[:ivars]['@other_user'].should == {
|
109
|
+
'class' => 'Aqua::Stub',
|
110
|
+
'init' => {'methods' => {'username' => 'strictnine' }, "class"=>"User", "id"=>""}
|
111
|
+
}
|
202
112
|
end
|
203
|
-
|
204
|
-
describe 'objects: ' do
|
205
|
-
# TODO: http://www.ruby-doc.org/core/
|
206
|
-
# make sure all the basic types work
|
207
113
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
@time.to_s.should == Time.parse( @pack[:ivars][:@created_at]['init'] ).to_s
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
describe 'true and false' do
|
222
|
-
it 'should save as self' do
|
223
|
-
@user.grab_bag = true
|
224
|
-
pack = @user._pack
|
225
|
-
pack[:ivars][:@grab_bag].should == true
|
226
|
-
|
227
|
-
@user.grab_bag = false
|
228
|
-
pack = @user._pack
|
229
|
-
pack[:ivars][:@grab_bag].should == false
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
describe 'Date' do
|
234
|
-
it 'should save as a hash with the class and to_s as the value' do
|
235
|
-
time_hash = @pack[:ivars][:@dob]
|
236
|
-
time_hash['class'].should == 'Date'
|
237
|
-
time_hash['init'].class.should == String
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'the value should be reconstitutable with Date.parse' do
|
241
|
-
@date.should == Date.parse( @pack[:ivars][:@dob]['init'] )
|
242
|
-
end
|
243
|
-
|
244
|
-
it 'should not pack internally used ivars as specified by the class' do
|
245
|
-
@pack[:ivars][:@dob][:ivars].keys.should_not include('@sg', '@of', '@ajd')
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
describe 'Numbers' do
|
250
|
-
it 'should pack Fixnums with correct class and value' do
|
251
|
-
pack = pack_grab_bag( 42 )
|
252
|
-
pack[:class].should == 'Fixnum'
|
253
|
-
pack[:init].should == '42'
|
254
|
-
end
|
255
|
-
|
256
|
-
it 'should pack Bignums with correct class and value' do
|
257
|
-
pack = pack_grab_bag( 123456789123456789 )
|
258
|
-
pack[:class].should == 'Bignum'
|
259
|
-
pack[:init].should == '123456789123456789'
|
260
|
-
end
|
261
|
-
|
262
|
-
it 'should pack Floats with correct class and value' do
|
263
|
-
pack = pack_grab_bag( 3.2 )
|
264
|
-
pack[:class].should == 'Float'
|
265
|
-
pack[:init].should == '3.2'
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'should pack Rationals with the correct class and values' do
|
269
|
-
pack = pack_grab_bag( Rational( 1, 17 ) )
|
270
|
-
pack[:class].should == 'Rational'
|
271
|
-
pack[:init].should == ['1', '17']
|
272
|
-
end
|
273
|
-
|
274
|
-
end
|
275
|
-
|
276
|
-
describe 'hashes with object as keys' do
|
277
|
-
it 'should pack an hash containing only strings/symbols for keys and values, with an init value that is that hash and a class key' do
|
278
|
-
@user.name = {'first' => 'Kane', 'last' => 'Baccigalupi'}
|
279
|
-
pack = @user._pack
|
280
|
-
pack[:ivars][:@name].should == {'class' => 'Hash', 'init' => {'first' => 'Kane', 'last' => 'Baccigalupi'} }
|
281
|
-
end
|
282
|
-
|
283
|
-
it 'should pack a numeric object key' do
|
284
|
-
pack = pack_grab_bag( {1 => 'first', 2 => 'second'} )
|
285
|
-
keys = pack[:init].keys
|
286
|
-
keys.should include( '/OBJECT_0', '/OBJECT_1' )
|
287
|
-
user_pack = @user.instance_variable_get("@__pack")
|
288
|
-
user_pack[:keys].size.should == 2
|
289
|
-
user_pack[:keys].first['class'].should == 'Fixnum'
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'should pack a more complex object as a key' do
|
293
|
-
struct = OpenStruct.new( :gerbil => true )
|
294
|
-
pack = pack_grab_bag( { struct => 'first'} )
|
295
|
-
keys = pack[:init].keys
|
296
|
-
keys.should include( '/OBJECT_0' )
|
297
|
-
user_pack = @user.instance_variable_get("@__pack")
|
298
|
-
user_pack[:keys].size.should == 1
|
299
|
-
user_pack[:keys].first['class'].should == 'OpenStruct'
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
describe 'embeddable aquatic' do
|
304
|
-
it 'aquatic objects should have packing instructions in the form of #_embed_me' do
|
305
|
-
@user._embed_me.should == {'stub' => :username }
|
306
|
-
Log.new._embed_me.should == true
|
307
|
-
User.configure_aqua( :embed => {:stub => [:username, :name] } )
|
308
|
-
@user._embed_me.should == { 'stub' => [:username, :name] }
|
309
|
-
# reset for future tests
|
310
|
-
User.configure_aqua( :embed => {:stub => :username } )
|
311
|
-
end
|
312
|
-
|
313
|
-
it 'should save their ivars correctly' do
|
314
|
-
@pack[:ivars][:@log].keys.should include('ivars')
|
315
|
-
@pack[:ivars][:@log]['ivars'].keys.should == ['@created_at', '@message']
|
316
|
-
@pack[:ivars][:@log]['ivars']['@message'].should == "Hello World! This is a log entry"
|
317
|
-
end
|
318
|
-
|
319
|
-
it 'should correctly pack Array derivatives' do
|
320
|
-
class Arrayed < Array
|
321
|
-
aquatic
|
322
|
-
attr_accessor :my_accessor
|
323
|
-
end
|
324
|
-
arrayish = Arrayed['a', 'b', 'c', 'd']
|
325
|
-
arrayish.my_accessor = 'Newt'
|
326
|
-
pack = arrayish._pack
|
327
|
-
pack.keys.should include('class', 'init', 'ivars')
|
328
|
-
pack['init'].class.should == Array
|
329
|
-
pack['init'].should == ['a', 'b', 'c', 'd']
|
330
|
-
pack['ivars']['@my_accessor'].should == 'Newt'
|
331
|
-
end
|
332
|
-
|
333
|
-
it 'should correctly pack Hash derivative' do
|
334
|
-
class Hashed < Hash
|
335
|
-
aquatic
|
336
|
-
attr_accessor :my_accessor
|
337
|
-
end
|
338
|
-
hashish = Hashed.new
|
339
|
-
hashish['1'] = '2'
|
340
|
-
hashish.my_accessor = 'Newt'
|
341
|
-
pack = hashish._pack
|
342
|
-
pack.keys.should include('class', 'init', 'ivars')
|
343
|
-
pack['init'].class.should == HashWithIndifferentAccess
|
344
|
-
pack['init'].should == {'1' => '2'}
|
345
|
-
pack['ivars']['@my_accessor'].should == 'Newt'
|
346
|
-
end
|
347
|
-
|
348
|
-
end
|
349
|
-
|
350
|
-
describe 'non-aquatic' do
|
351
|
-
before(:each) do
|
352
|
-
@struct = OpenStruct.new(
|
353
|
-
:gerbil => true,
|
354
|
-
:cat => 'yup, that too!',
|
355
|
-
:disaster => ['pow', 'blame', 'chase', 'spew']
|
356
|
-
)
|
357
|
-
@grounded = Grounded.new(
|
358
|
-
:openly_structured => @struct,
|
359
|
-
:hash_up => {:this => 'that'},
|
360
|
-
:arraynged => ['swimming', 'should', 'be easy', 'if you float']
|
361
|
-
)
|
362
|
-
|
363
|
-
end
|
364
|
-
|
365
|
-
describe 'OpenStructs' do
|
366
|
-
before(:each) do
|
367
|
-
@user.grab_bag = @struct
|
368
|
-
pack = @user._pack
|
369
|
-
@grab_bag = pack[:ivars][:@grab_bag]
|
370
|
-
end
|
371
|
-
|
372
|
-
it 'the key "class" should map to "OpenStruct"' do
|
373
|
-
@grab_bag['class'].should == 'OpenStruct'
|
374
|
-
end
|
375
|
-
|
376
|
-
it 'the key "ivars" should have the key "@table", a private variable' do
|
377
|
-
@grab_bag['ivars'].keys.should_not == ['@table']
|
378
|
-
end
|
379
|
-
|
380
|
-
it 'should initialize with the @table instance variable' do
|
381
|
-
init_keys = @grab_bag['init'].keys
|
382
|
-
init_keys.should include(':cat')
|
383
|
-
init_keys.should include(':disaster')
|
384
|
-
init_keys.should include(':gerbil')
|
385
|
-
@grab_bag['init'][':gerbil'].should == true
|
386
|
-
@grab_bag['init'][':cat'].should == 'yup, that too!'
|
387
|
-
@grab_bag['init'][':disaster'].should == {'class' => 'Array', 'init' => ['pow', 'blame', 'chase', 'spew']}
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
describe 'Uninherited classes with deep nesting' do
|
392
|
-
before(:each) do
|
393
|
-
@user.grab_bag = @grounded
|
394
|
-
pack = @user._pack
|
395
|
-
@grab_bag = pack[:ivars][:@grab_bag]
|
396
|
-
end
|
397
|
-
|
398
|
-
it 'the key "class" should map correctly to the class name' do
|
399
|
-
@grab_bag['class'].should == 'Grounded'
|
400
|
-
end
|
401
|
-
|
402
|
-
it 'should have ivars keys for all the ivars' do
|
403
|
-
keys = @grab_bag[:ivars].keys
|
404
|
-
keys.should include('@openly_structured')
|
405
|
-
keys.should include('@hash_up')
|
406
|
-
keys.should include('@arraynged')
|
407
|
-
end
|
408
|
-
|
409
|
-
it 'should correctly display the nested OpenStruct' do
|
410
|
-
user_2 = User.new(:grab_bag => @struct) # this has already been tested in the set above
|
411
|
-
user_2._pack[:ivars][:@grab_bag].should == @grab_bag[:ivars][:@openly_structured]
|
412
|
-
end
|
413
|
-
end
|
414
|
-
|
415
|
-
describe 'Classes inherited from Array' do
|
416
|
-
before(:each) do
|
417
|
-
@struct = OpenStruct.new(
|
418
|
-
:gerbil => true,
|
419
|
-
:cat => 'yup, that too!',
|
420
|
-
:disaster => ['pow', 'blame', 'chase', 'spew'],
|
421
|
-
:nipples => 'yes'
|
422
|
-
)
|
423
|
-
@strange_array = ArrayUdder['cat', 'octopus', @struct ]
|
424
|
-
@strange_array.udder # sets an instance variable
|
425
|
-
@user.grab_bag = @strange_array
|
426
|
-
pack = @user._pack
|
427
|
-
@grab_bag = pack[:ivars][:@grab_bag]
|
428
|
-
end
|
429
|
-
|
430
|
-
it 'should correctly map the class name' do
|
431
|
-
@grab_bag[:class].should == 'ArrayUdder'
|
432
|
-
end
|
433
|
-
|
434
|
-
it 'should store the instance variables' do
|
435
|
-
@grab_bag[:ivars].keys.should == ['@udder']
|
436
|
-
end
|
437
|
-
|
438
|
-
it 'should store the simple array values' do
|
439
|
-
@grab_bag[:init].should_not be_nil
|
440
|
-
@grab_bag[:init].class.should == Array
|
441
|
-
@grab_bag[:init].should include('cat')
|
442
|
-
@grab_bag[:init].should include('octopus')
|
443
|
-
end
|
444
|
-
|
445
|
-
it 'should store the more complex array values correctly' do
|
446
|
-
user_2 = User.new(:grab_bag => @struct) # this has already been tested in the set above
|
447
|
-
user_2._pack[:ivars][:@grab_bag].should == @grab_bag[:init].last
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
describe 'Classes inherited from Hash' do
|
452
|
-
before(:each) do
|
453
|
-
@struct = OpenStruct.new(
|
454
|
-
:gerbil => true,
|
455
|
-
:cat => 'yup, that too!',
|
456
|
-
:disaster => ['pow', 'blame', 'chase', 'spew'],
|
457
|
-
:nipples => 'yes'
|
458
|
-
)
|
459
|
-
@hash_derivative = CannedHash.new(
|
460
|
-
:ingredients => ['Corned Beef', 'Potatoes', 'Tin Can'],
|
461
|
-
:healthometer => false,
|
462
|
-
:random_struct => @struct
|
463
|
-
)
|
464
|
-
@hash_derivative.yum # sets an instance variable
|
465
|
-
@user.grab_bag = @hash_derivative
|
466
|
-
pack = @user._pack
|
467
|
-
@grab_bag = pack[:ivars][:@grab_bag]
|
468
|
-
end
|
469
|
-
|
470
|
-
it 'should correctly map the class name' do
|
471
|
-
@grab_bag[:class].should == 'CannedHash'
|
472
|
-
end
|
473
|
-
|
474
|
-
it 'should store the instance variables' do
|
475
|
-
@grab_bag[:ivars].keys.should == ['@yum']
|
476
|
-
end
|
477
|
-
|
478
|
-
it 'should store the simple hash values' do
|
479
|
-
@grab_bag[:init].should_not be_nil
|
480
|
-
@grab_bag[:init].class.should == HashWithIndifferentAccess
|
481
|
-
|
482
|
-
@grab_bag[:init].keys.should include('ingredients')
|
483
|
-
@grab_bag[:init].keys.should include('healthometer')
|
484
|
-
@grab_bag[:init].keys.should include('random_struct')
|
485
|
-
end
|
486
|
-
|
487
|
-
it 'should store the more complex hash values correctly' do
|
488
|
-
user_2 = User.new(:grab_bag => @struct) # this has already been tested in the set above
|
489
|
-
user_2._pack[:ivars][:@grab_bag].should == @grab_bag[:init][:random_struct]
|
490
|
-
end
|
491
|
-
end
|
492
|
-
|
493
|
-
describe 'Embedded IO:' do
|
494
|
-
before(:each) do
|
495
|
-
@file = File.new(File.dirname(__FILE__) + '/../store/couchdb/fixtures_and_data/image_attach.png')
|
496
|
-
@tempfile = Tempfile.new('temp.txt')
|
497
|
-
@tempfile.write('I am a tempfile!')
|
498
|
-
@tempfile.rewind
|
499
|
-
end
|
500
|
-
|
501
|
-
describe "File" do
|
502
|
-
it 'should have pack its class name as Aqua::FileStub' do
|
503
|
-
@user.grab_bag = @file
|
504
|
-
@user._pack
|
505
|
-
@user._pack[:ivars][:@grab_bag][:class].should == 'Aqua::FileStub'
|
506
|
-
end
|
507
|
-
|
508
|
-
it 'should have pack with an initialization key' do
|
509
|
-
@user.grab_bag = @file
|
510
|
-
pack = @user._pack
|
511
|
-
pack[:ivars][:@grab_bag][:init].should == '/FILE_image_attach.png'
|
512
|
-
end
|
513
|
-
|
514
|
-
it 'should add an attachment to the pack' do
|
515
|
-
@user.grab_bag = @file
|
516
|
-
pack = @user._pack
|
517
|
-
pack.attachments.size.should == 1
|
518
|
-
pack.attachments.get('image_attach.png').should == @file
|
519
|
-
end
|
520
|
-
|
521
|
-
it 'should stub content type and length' do
|
522
|
-
@user.grab_bag = @file
|
523
|
-
pack = @user._pack
|
524
|
-
pack[:ivars][:@grab_bag][:methods].should include('content_type', 'content_length')
|
525
|
-
pack[:ivars][:@grab_bag][:methods]['content_type'].should == 'image/png'
|
526
|
-
pack[:ivars][:@grab_bag][:methods]['content_length'].should == 26551
|
527
|
-
end
|
528
|
-
end
|
529
|
-
|
530
|
-
describe 'Tempfile' do
|
531
|
-
it 'should have pack its class name as Aqua::FileStub' do
|
532
|
-
@user.grab_bag = @tempfile
|
533
|
-
@user._pack
|
534
|
-
@user._pack[:ivars][:@grab_bag][:class].should == 'Aqua::FileStub'
|
535
|
-
end
|
536
|
-
|
537
|
-
it 'should have pack with an initialization key' do
|
538
|
-
@user.grab_bag = @tempfile
|
539
|
-
pack = @user._pack
|
540
|
-
pack[:ivars][:@grab_bag][:init].should == '/FILE_temp.txt'
|
541
|
-
end
|
542
|
-
|
543
|
-
it 'should add an attachment to the pack' do
|
544
|
-
@user.grab_bag = @tempfile
|
545
|
-
pack = @user._pack
|
546
|
-
pack.attachments.size.should == 1
|
547
|
-
pack.attachments.get('temp.txt').path.should == @tempfile.path
|
548
|
-
end
|
549
|
-
end
|
550
|
-
end
|
551
|
-
end
|
114
|
+
it 'should commit the external when saving the base object' do
|
115
|
+
@user.commit!
|
116
|
+
@other_user.id.should_not be_nil
|
117
|
+
@other_user.id.should_not == @other_user.object_id
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should commit external objects' do
|
121
|
+
@user.should_receive(:_commit_externals)
|
122
|
+
@user.commit!
|
552
123
|
end
|
124
|
+
|
125
|
+
it 'should update the stubbed object id correctly' do
|
126
|
+
@user.instance_eval "_commit_externals"
|
127
|
+
@other_user.id.should_not be_empty
|
128
|
+
pack = @user._pack
|
129
|
+
pack[:ivars]['@other_user']['init']['id'].should == @other_user.id
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should save the document with the correct external ids' do
|
133
|
+
@user.commit!
|
134
|
+
document = User._get_store( @user.id )
|
135
|
+
document[:ivars]['@other_user']['init']['id'].should_not be_empty
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'transactions' do
|
139
|
+
it 'should rollback all externals if an one external fails to commit'
|
140
|
+
it 'should rollback all externals if the base object fails to commit'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe 'pack ids and revs' do
|
146
|
+
before(:each) do
|
147
|
+
build_user_ivars
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should have a _rev if it is present in the base object' do
|
151
|
+
@user.instance_variable_set("@_rev", '1-2222222')
|
152
|
+
pack = @user._pack
|
153
|
+
pack[:_rev].should == '1-2222222'
|
553
154
|
end
|
554
|
-
|
155
|
+
|
156
|
+
it 'should not have a _rev of nil if _rev is not provided in the base' do
|
157
|
+
@pack[:_rev].should == nil
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should initially have an id of nil' do
|
161
|
+
@pack[:_rev].should == nil
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should pack the id if it exists in the base' do
|
165
|
+
@user.id = 'my_id'
|
166
|
+
pack = @user._pack
|
167
|
+
pack[:_id].should == 'my_id'
|
168
|
+
end
|
169
|
+
end
|
555
170
|
|
556
|
-
describe '
|
557
|
-
before(:each) do
|
171
|
+
describe 'commit' do
|
172
|
+
before(:each) do
|
173
|
+
build_user_ivars
|
558
174
|
User::Storage.database.delete_all
|
559
175
|
end
|
560
176
|
|
561
|
-
it 'commit! should not raise errors on successful save' do
|
177
|
+
it 'commit! should not raise errors on successful save' do
|
562
178
|
lambda{ @user.commit! }.should_not raise_error
|
563
179
|
end
|
564
180
|
|
@@ -578,7 +194,7 @@ describe Aqua::Pack do
|
|
578
194
|
@user.instance_variable_get('@_rev').should_not be_nil
|
579
195
|
end
|
580
196
|
|
581
|
-
it 'commit! should save the record to CouchDB' do
|
197
|
+
it 'commit! should save the record to CouchDB' do
|
582
198
|
@user.commit!
|
583
199
|
lambda{ CouchDB.get( "http://127.0.0.1:5984/aqua/#{@user.id}") }.should_not raise_error
|
584
200
|
end
|
@@ -597,11 +213,15 @@ describe Aqua::Pack do
|
|
597
213
|
@user.commit.should == false
|
598
214
|
end
|
599
215
|
|
600
|
-
it 'should be able to update and commit again' do
|
216
|
+
it 'should be able to update and commit again without conflict' do
|
601
217
|
@user.commit!
|
602
218
|
@user.grab_bag = {'1' => '2'}
|
603
219
|
lambda{ @user.commit! }.should_not raise_error
|
604
220
|
end
|
605
221
|
end
|
606
|
-
|
222
|
+
|
223
|
+
describe 'classes' do
|
224
|
+
it 'should have a separate database'
|
225
|
+
end
|
226
|
+
|
607
227
|
end
|