riakrest 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +41 -0
  3. data/PostInstall.txt +2 -0
  4. data/README.rdoc +51 -0
  5. data/Rakefile +24 -0
  6. data/examples/auto_update_data.rb +50 -0
  7. data/examples/auto_update_links.rb +48 -0
  8. data/examples/basic_client.rb +33 -0
  9. data/examples/basic_resource.rb +34 -0
  10. data/examples/json_data_resource.rb +32 -0
  11. data/examples/linked_resource.rb +113 -0
  12. data/examples/multiple_resources.rb +43 -0
  13. data/lib/riakrest/core/exceptions.rb +73 -0
  14. data/lib/riakrest/core/jiak_bucket.rb +146 -0
  15. data/lib/riakrest/core/jiak_client.rb +316 -0
  16. data/lib/riakrest/core/jiak_data.rb +265 -0
  17. data/lib/riakrest/core/jiak_link.rb +131 -0
  18. data/lib/riakrest/core/jiak_object.rb +233 -0
  19. data/lib/riakrest/core/jiak_schema.rb +242 -0
  20. data/lib/riakrest/core/query_link.rb +156 -0
  21. data/lib/riakrest/data/jiak_data_hash.rb +182 -0
  22. data/lib/riakrest/resource/jiak_resource.rb +628 -0
  23. data/lib/riakrest/version.rb +7 -0
  24. data/lib/riakrest.rb +164 -0
  25. data/riakrest.gemspec +38 -0
  26. data/script/console +10 -0
  27. data/script/destroy +14 -0
  28. data/script/generate +14 -0
  29. data/spec/core/exceptions_spec.rb +18 -0
  30. data/spec/core/jiak_bucket_spec.rb +103 -0
  31. data/spec/core/jiak_client_spec.rb +358 -0
  32. data/spec/core/jiak_link_spec.rb +77 -0
  33. data/spec/core/jiak_object_spec.rb +210 -0
  34. data/spec/core/jiak_schema_spec.rb +184 -0
  35. data/spec/core/query_link_spec.rb +128 -0
  36. data/spec/data/jiak_data_hash_spec.rb +14 -0
  37. data/spec/resource/jiak_resource_spec.rb +128 -0
  38. data/spec/riakrest_spec.rb +17 -0
  39. data/spec/spec.opts +5 -0
  40. data/spec/spec_helper.rb +12 -0
  41. data/tasks/rspec.rake +21 -0
  42. metadata +113 -0
@@ -0,0 +1,358 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ class FooBarBaz # :nodoc:
4
+ include JiakData
5
+
6
+ allowed :foo, :bar, :baz
7
+ required :foo
8
+ readable :foo, :bar
9
+ writable :foo, :bar
10
+
11
+ def initialize(hsh)
12
+ hsh.each {|key,val| send("#{key}=",val)}
13
+ end
14
+
15
+ def self.jiak_create(jiak)
16
+ new(jiak)
17
+ end
18
+
19
+ def for_jiak
20
+ { :foo => @foo,
21
+ :bar => @bar
22
+ }.reject {|k,v| v.nil?}
23
+ end
24
+
25
+ def eql?(other)
26
+ other.is_a?(FooBarBaz) && other.foo.eql?(@foo) && other.bar.eql?(@bar)
27
+ end
28
+ end
29
+
30
+ describe "JiakClient" do
31
+ before do
32
+ @base_uri = 'http://127.0.0.1:8002/jiak/'
33
+ @client = JiakClient.new @base_uri
34
+ end
35
+
36
+ it "should respond to" do
37
+ @client.should respond_to(:set_schema, :schema, :keys)
38
+ @client.should respond_to(:uri)
39
+ @client.should respond_to(:==,:eql?)
40
+ @client.should respond_to(:get, :store, :delete, :walk)
41
+ end
42
+
43
+ it "should default to base URI" do
44
+ @client.uri.should match @base_uri
45
+ end
46
+
47
+ it "should allow specified base URI" do
48
+ base_uri = 'http://localhost:1234/tmp/'
49
+ client = JiakClient.new base_uri
50
+ client.uri.should match base_uri
51
+ end
52
+
53
+ it "should equal another JiakClient with the same URI" do
54
+ client = JiakClient.new @base_uri
55
+ client.should eql @client
56
+ client.should == @client
57
+ end
58
+
59
+ end
60
+
61
+ describe "JiakClient URI handling" do
62
+ before do
63
+ @base_uri = 'http://127.0.0.1:8002/jiak/'
64
+ @client = JiakClient.new @base_uri
65
+ @bucket = JiakBucket.new('uri_bucket',FooBarBaz)
66
+ @key = 'uri_key'
67
+ end
68
+ end
69
+
70
+ describe "JiakClient processing" do
71
+ before do
72
+ @base_uri = 'http://127.0.0.1:8002/jiak/'
73
+ @client = JiakClient.new @base_uri
74
+ end
75
+
76
+ describe "for buckets" do
77
+ before do
78
+ @bucket_name = 'bucket_1'
79
+ @bucket = JiakBucket.new(@bucket_name,FooBarBaz)
80
+ @client.set_schema(@bucket)
81
+ end
82
+
83
+ it "should create and fetch a bucket schema" do
84
+ schema = @client.schema(@bucket)
85
+
86
+ ['allowed_fields',
87
+ 'required_fields',
88
+ 'read_mask',
89
+ 'write_mask'].each do |fields|
90
+ schema_fields = schema.send("#{fields}")
91
+ fbb_fields = FooBarBaz.schema.send("#{fields}")
92
+ schema_fields.same_fields?(fbb_fields).should be true
93
+ end
94
+ end
95
+
96
+ it "should update an existing bucket schema" do
97
+ FooBarBazBuz = JiakDataHash.create(:foo,:bar,:baz,:buz)
98
+ @client.set_schema(JiakBucket.new(@bucket_name,FooBarBazBuz))
99
+
100
+ resp_schema = @client.schema(@bucket)
101
+ resp_schema.allowed_fields.should include 'buz'
102
+ resp_schema.required_fields.should be_empty
103
+ resp_schema.read_mask.should include 'baz'
104
+ resp_schema.write_mask.should include 'baz'
105
+
106
+ end
107
+
108
+ it "should get a list of keys for a bucket" do
109
+ arr = [{:key=>'key1',:dobj=>FooBarBaz.new(:foo=>'v1')},
110
+ {:key=>'key2',:dobj=>FooBarBaz.new(:foo=>'v21',:bar=>'v22')},
111
+ {:key=>'',:dobj=>FooBarBaz.new(:foo=>'v3')}]
112
+ keys = arr.map do |hsh|
113
+ jo = JiakObject.new(:bucket => @bucket,
114
+ :key => hsh[:key],
115
+ :data => hsh[:dobj])
116
+ @client.store(jo)
117
+ end
118
+ srv_keys = @client.keys(@bucket)
119
+ keys.each {|key| srv_keys.should include key}
120
+ end
121
+
122
+ it "should encode odd bucket strings" do
123
+ bucket_name = "# <& %"
124
+ bucket = JiakBucket.new(bucket_name,FooBarBaz)
125
+ @client.set_schema(bucket)
126
+ schema = @client.schema(@bucket)
127
+ FooBarBaz.schema.read_mask.same_fields?(schema.read_mask).should be true
128
+ end
129
+ end
130
+
131
+ describe "for CRUD" do
132
+ before do
133
+ @bucket = JiakBucket.new('bucket_2',FooBarBaz)
134
+ @client.set_schema(@bucket)
135
+ @data = FooBarBaz.new(:foo => 'foo val')
136
+ end
137
+
138
+ describe "storage" do
139
+ it "should store a JiakObject by the specified key" do
140
+ key = 'store_key_1'
141
+ jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
142
+ resp = @client.store(jobj)
143
+ resp.should eql key
144
+ end
145
+
146
+ it "should store a JiakObject w/o a key" do
147
+ jobj = JiakObject.new(:bucket => @bucket, :data => @data)
148
+ resp = @client.store(jobj)
149
+ resp.should_not be_empty
150
+ end
151
+
152
+ it "should return a JiakObject at time of storage" do
153
+ key = 'store_key_2'
154
+ jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
155
+ resp = @client.store(jobj,{:object => true})
156
+ resp.should be_a JiakObject
157
+ resp.bucket.should eql @bucket
158
+ resp.key.should eql key
159
+ resp.data.should be_a FooBarBaz
160
+
161
+ jobj = JiakObject.new(:bucket => @bucket, :data => @data)
162
+ resp = @client.store(jobj,{:object => true})
163
+ resp.should be_a JiakObject
164
+ resp.key.should_not be_nil
165
+ resp.data.should be_a FooBarBaz
166
+ end
167
+
168
+ it "should handle odd key values" do
169
+ key = '$ p @ c #'
170
+ jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
171
+ resp_key = @client.store(jobj)
172
+ resp_key.should eql key
173
+ end
174
+ end
175
+
176
+ describe "fetching" do
177
+ it "should get a previously stored JiakObject" do
178
+ key = 'fetch_key_1'
179
+ jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
180
+ @client.store(jobj)
181
+
182
+ fetched = @client.get(@bucket,key)
183
+ fetched.should be_a JiakObject
184
+ fetched.bucket.should eql @bucket
185
+ fetched.key.should eql key
186
+ fetched.data.should eql jobj.data
187
+
188
+ jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
189
+ key = @client.store(jobj)
190
+ fetched = @client.get(@bucket,key)
191
+ fetched.should be_a JiakObject
192
+ end
193
+
194
+ it "should raise JiakResourceNotFound for a non-existent key" do
195
+ get_nope = lambda {@client.get(@bucket,'nope')}
196
+ get_nope.should raise_error(JiakResourceNotFound)
197
+ end
198
+ end
199
+
200
+ describe "updating" do
201
+ it "should update a previously stored JiakObject" do
202
+ jobj =
203
+ @client.store(JiakObject.new(:bucket => @bucket, :data => @data),
204
+ {:object => true})
205
+
206
+ jobj.data.should eql @data
207
+ [:vclock,:vtag,:lastmod].each do |field|
208
+ jobj.riak.should include field
209
+ jobj.riak[field].should be_a String
210
+ jobj.riak[field].should_not be_empty
211
+ end
212
+
213
+ updated_data = FooBarBaz.new(:foo => 'new val')
214
+ jobj.data = updated_data
215
+ updated_object =
216
+ @client.store(jobj,{:object => true})
217
+ updated_data = updated_object.data
218
+ updated_data.should_not eql @data
219
+ updated_data.foo.should eql 'new val'
220
+ updated_object.riak[:vclock].should_not eql jobj.riak[:vclock]
221
+ updated_object.riak[:vtag].should_not eql jobj.riak[:vtag]
222
+ end
223
+ end
224
+
225
+ describe "deleting" do
226
+ it "should remove a previously stored JiakObject" do
227
+ key = 'delete_key_1'
228
+ jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
229
+ @client.store(jobj)
230
+
231
+ @client.delete(@bucket,key).should be true
232
+ get_deleted = lambda {@client.get(@bucket,key)}
233
+ get_deleted.should raise_error(JiakResourceNotFound)
234
+ end
235
+ end
236
+ end
237
+
238
+ end
239
+
240
+ Parent = JiakDataHash.create(:name)
241
+ Child = JiakDataHash.create(:name)
242
+
243
+ describe "JiakClient links" do
244
+ before do
245
+ @base_uri = 'http://127.0.0.1:8002/jiak/'
246
+ @client = JiakClient.new @base_uri
247
+
248
+ @p_bucket = JiakBucket.new('parent',Parent)
249
+ @c_bucket = JiakBucket.new('child',Child)
250
+ @client.set_schema(@p_bucket)
251
+ @client.set_schema(@c_bucket)
252
+ end
253
+
254
+ it "should add links and walk the resulting structure" do
255
+ parent_children = {
256
+ 'p1' => ['c1','c2'],
257
+ 'p2' => ['c2','c3','c4'],
258
+ 'p3' => ['c4','c5','c6'],
259
+ 'p4' => ['c5','c6'],
260
+ 'p5' => ['c7']
261
+ }
262
+
263
+ # invert the p/c relationships
264
+ child_parents = parent_children.inject({}) do |build, (p,cs)|
265
+ cs.each do |c|
266
+ build[c] ? build[c] << p : build[c] = [p]
267
+ end
268
+ build
269
+ end
270
+
271
+ # for each p/c relation
272
+ # - create p and c (when necessary)
273
+ # - add links for p -> c and c -> p
274
+ parent_children.each do |p_name,c_names|
275
+ p_data = Parent.new(:name => p_name)
276
+ p_obj = JiakObject.new(:bucket => @p_bucket,
277
+ :key => p_name,
278
+ :data => p_data)
279
+ parent = @client.store(p_obj,:object => true)
280
+ p_link = JiakLink.new(@p_bucket,parent.key,'parent')
281
+ c_names.each do |c_name|
282
+ begin
283
+ child = @client.get(@c_bucket,c_name)
284
+ rescue JiakResourceNotFound
285
+ c_data = Child.new(:name => c_name)
286
+ c_obj = JiakObject.new(:bucket => @c_bucket,
287
+ :key => c_name,
288
+ :data => c_data)
289
+ child = @client.store(c_obj, :object => true)
290
+ end
291
+ c_link = JiakLink.new(@c_bucket,child.key,'child')
292
+ child << p_link
293
+ @client.store(child)
294
+ parent << c_link
295
+ end
296
+ @client.store(parent)
297
+ end
298
+
299
+ # get the number of links in the p's
300
+ p1,p2,p3,p4,p5 = parent_children.keys.map {|p| @client.get(@p_bucket,p)}
301
+ [p1,p4].each {|p| p.links.should have_exactly(2).items}
302
+ [p2,p3].each {|p| p.links.should have_exactly(3).items}
303
+ p5.links.should have_exactly(1).item
304
+
305
+ # get the number of links in the c's
306
+ c1,c2,c3,c4,c5,c6,c7 = child_parents.keys.map {|c| @client.get(@c_bucket,c)}
307
+ [c1,c3,c7].each {|c| c.links.should have_exactly(1).items}
308
+ [c2,c4,c5,c6].each {|c| c.links.should have_exactly(2).items}
309
+
310
+ # check the links in each p and c
311
+ p_link = JiakLink.new(@p_bucket,'k','parent')
312
+ c_link = JiakLink.new(@c_bucket,'k','child')
313
+ parent_children.each do |p_name,children|
314
+ parent = @client.get(@p_bucket,p_name)
315
+ links = parent.links
316
+ children.each do |c_name|
317
+ c_link.key = c_name
318
+ parent.links.should include c_link
319
+
320
+ child = @client.get(@c_bucket,c_name)
321
+ p_link.key = p_name
322
+ child.links.should include p_link
323
+ end
324
+ end
325
+
326
+ # p's should include links to their c's
327
+ c_link = QueryLink.new(@c_bucket,'child',nil)
328
+ parent_children.each do |p_name,children|
329
+ @client.walk(@p_bucket,p_name,c_link,Child).each do |c_obj|
330
+ children.should include c_obj.data.name
331
+ end
332
+ end
333
+
334
+ # c's should include links to their p's
335
+ p_link = QueryLink.new(@p_bucket,'parent',nil)
336
+ child_parents.each do |c_name,parents|
337
+ @client.walk(@c_bucket,c_name,p_link,Parent).each do |p_obj|
338
+ parents.should include p_obj.data.name
339
+ end
340
+ end
341
+
342
+ # c siblings requires a second step
343
+ c1s,c2s,c3s,c4s,c5s,c6s,c7s = child_parents.keys.map do |c|
344
+ siblings = @client.walk(@c_bucket,c,[p_link,c_link],Child)
345
+ me = @client.get(@c_bucket,c)
346
+ siblings.reject! {|s| s.eql?(me)}
347
+ siblings
348
+ end
349
+ c1s.should have_exactly(1).item
350
+ c2s.should have_exactly(3).items
351
+ c3s.should have_exactly(2).items
352
+ c4s.should have_exactly(4).items
353
+ c5s.should have_exactly(2).items
354
+ c6s.should have_exactly(2).items
355
+ c7s.should have_exactly(0).items
356
+ end
357
+
358
+ end
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "JiakLink" do
4
+ before do
5
+ @bucket = 'b'
6
+ @key = 'k'
7
+ @tag = 't'
8
+ @jiak_link = JiakLink.new(@bucket,@key,@tag)
9
+ end
10
+
11
+ it "should respond to" do
12
+ @jiak_link.should respond_to(:bucket,:key,:tag)
13
+ @jiak_link.should respond_to(:bucket=,:key=,:tag=)
14
+
15
+ @jiak_link.should respond_to(:for_jiak)
16
+
17
+ @jiak_link.should respond_to(:eql?,:==)
18
+ end
19
+
20
+ it "should init from specified values" do
21
+ @jiak_link.bucket.should eql @bucket
22
+ @jiak_link.key.should eql @key
23
+ @jiak_link.tag.should eql @tag
24
+
25
+ jiak_link = JiakLink.new(@jiak_link)
26
+ jiak_link.bucket.should eql @bucket
27
+ jiak_link.key.should eql @key
28
+ jiak_link.tag.should eql @tag
29
+
30
+ jiak_link = JiakLink.new(['b','k','t'])
31
+ jiak_link.bucket.should eql 'b'
32
+ jiak_link.key.should eql 'k'
33
+ jiak_link.tag.should eql 't'
34
+ end
35
+
36
+ it "should ignore leading/trailing spaces for opts on init" do
37
+ bucket = " "+@bucket+" "
38
+ key = " "+@key+" "
39
+ tag = " "+@tag+" "
40
+ jiak_link = JiakLink.new(bucket,key,tag)
41
+ jiak_link.bucket.should eql @bucket
42
+ jiak_link.key.should eql @key
43
+ jiak_link.tag.should eql @tag
44
+ end
45
+
46
+ it "should reject blank, empty strings, or nil values on init" do
47
+ [""," ",nil].each do |bucket|
48
+ bad_bucket = lambda { JiakLink.new(bucket,'k','t') }
49
+ bad_bucket.should raise_error(JiakLinkException)
50
+ end
51
+ end
52
+
53
+ it "should allow field updates" do
54
+ @jiak_link.bucket = 'new_bucket'
55
+ @jiak_link.bucket.should eql 'new_bucket'
56
+ @jiak_link.key = 'new_key'
57
+ @jiak_link.key.should eql 'new_key'
58
+ @jiak_link.tag = 'new_tag'
59
+ @jiak_link.tag.should eql 'new_tag'
60
+ end
61
+
62
+ it "should convert for Jiak" do
63
+ @jiak_link.for_jiak.should eql [@bucket,@key,@tag]
64
+ end
65
+
66
+ it "should compare to another JiakLink via eql?" do
67
+ jiak_link_1 = JiakLink.new('a','b','c')
68
+ jiak_link_2 = JiakLink.new('a','b','c')
69
+ jiak_link_3 = JiakLink.new('a','~b','c')
70
+
71
+ jiak_link_1.should eql jiak_link_2
72
+ jiak_link_1.should_not eql jiak_link_3
73
+
74
+ jiak_link_1.should == jiak_link_2
75
+ jiak_link_1.should_not == jiak_link_3
76
+ end
77
+ end
@@ -0,0 +1,210 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ DataObject = JiakDataHash.create(:f1,:f2,:f3)
4
+
5
+ describe "JiakObject" do
6
+ before do
7
+ @data =
8
+ DataObject.new(:f1 => 'f1',:f2 => ['a','b'], :f3 => {:f3_1 => 'f3_1'})
9
+ @bucket_name = 'bucket'
10
+ @bucket = JiakBucket.new(@bucket_name,DataObject)
11
+ @key = 'hey'
12
+ @l1 = JiakLink.new('l1b','l1k','l1t')
13
+ @l2 = JiakLink.new('l2b','l2k','l2t')
14
+ @links = [@l1,@l2]
15
+
16
+ object = @data.for_jiak
17
+ links = @links.map {|link| link.for_jiak}
18
+
19
+ core = {
20
+ :bucket => @bucket_name, :key => @key,
21
+ :object => object, :links => links
22
+ }
23
+ full = core.merge(:vclock=>'vclock',:vtag=>'vtag',:lastmod=>'last mod')
24
+ @core_json = core.to_json
25
+ @full_json = full.to_json
26
+ @object = JiakObject.new(:bucket => @bucket,
27
+ :key => @key,
28
+ :data => @data,
29
+ :links => @links)
30
+ end
31
+
32
+ it "should respond to" do
33
+ JiakObject.should respond_to(:new,:from_jiak)
34
+
35
+ @object.should respond_to(:bucket,:bucket=)
36
+ @object.should respond_to(:key,:key=)
37
+ @object.should respond_to(:data,:data=)
38
+ @object.should respond_to(:links,:links=)
39
+ @object.should respond_to(:riak,:riak=)
40
+ @object.should respond_to(:<<)
41
+ @object.should respond_to(:==,:eql?)
42
+ @object.should respond_to(:to_jiak)
43
+ end
44
+
45
+ it "should initialize with bucket, key and data" do
46
+ @object.bucket.should eql @bucket
47
+ @object.key.should eql @key
48
+ @object.data.should be_a JiakData
49
+ @object.data.should eql @data
50
+ @object.links.should be_an Array
51
+ @object.links.should eql @links
52
+
53
+ jobj = JiakObject.new(:bucket => @bucket, :key => @key, :data => @data)
54
+ jobj.bucket.should eql @bucket
55
+ jobj.links.should be_empty
56
+ end
57
+
58
+ it "should allow nil, missing, blank or empty key" do
59
+ [nil,'',' '].each do |key|
60
+ JiakObject.new(:bucket => @bucket, :data => @data,
61
+ :key => key ).key.should be_empty
62
+ end
63
+ JiakObject.new(:bucket => @bucket, :data => @data).key.should be_empty
64
+ end
65
+
66
+
67
+ it "should initialize with specified links" do
68
+ @object.links.should equal @links
69
+ end
70
+
71
+ it "should initialize from JSON" do
72
+ [@core_json,@full_json].each do |json|
73
+ jiak = JSON.parse(json)
74
+ jobj = JiakObject.from_jiak(jiak,@bucket.data_class)
75
+ jobj.bucket.should eql @object.bucket
76
+ jobj.key.should eql @object.key
77
+ jobj.data.f1.should eql @data.f1
78
+ jobj.data.f2.should eql @data.f2
79
+ jobj.data.f3['f3_1'].should eql @data.f3[:f3_1]
80
+
81
+ jobj.links.size.should == @object.links.size
82
+ jlinks = jobj.links
83
+ olinks = @object.links
84
+ same = jlinks.reduce(true) {|same,value| same && olinks.include?(value)}
85
+ same.should be true
86
+ end
87
+
88
+ jiak = JSON.parse(@full_json)
89
+ jobj = JiakObject.from_jiak(jiak,@bucket.data_class)
90
+ jobj.riak[:vclock].should eql 'vclock'
91
+ jobj.riak[:vtag].should eql 'vtag'
92
+ jobj.riak[:lastmod].should eql 'last mod'
93
+ end
94
+
95
+ it "should raise JiakObjectException for nil bucket" do
96
+ nil_bucket = lambda {JiakObject.new(:bucket => nil,:data_obect => @data)}
97
+ nil_bucket.should raise_error(JiakObjectException)
98
+ no_bucket = lambda {JiakObject.new(:data_obect => @data)}
99
+ no_bucket.should raise_error(JiakObjectException)
100
+ end
101
+
102
+ it "should raise JiakObjectException if object not a JiakData" do
103
+ bad_data = lambda {JiakObject.new(:bucket=>@bucket,:data=>'a')}
104
+ bad_data.should raise_error(JiakObjectException,/JiakData/)
105
+ no_data = lambda {JiakObject.new(:bucket=>@bucket)}
106
+ no_data.should raise_error(JiakObjectException,/JiakData/)
107
+ end
108
+
109
+ it "should raise JiakObjectException if link not an Array" do
110
+ link_not_array = lambda {JiakObject.new(:bucket => @bucket,
111
+ :data => @data,
112
+ :links =>"l")}
113
+ link_not_array.should raise_error(JiakObjectException,/array/)
114
+ end
115
+
116
+ it "should raise JiakObjectException if each link is not a JiakLink" do
117
+ links = [@l1,'l',@l2]
118
+ bad_link = lambda {JiakObject.new(:bucket => @bucket,
119
+ :data => @data,
120
+ :links => [@l1,'l',@l2])}
121
+ bad_link.should raise_error(JiakObjectException,/JiakLink/)
122
+ end
123
+
124
+ it "should convert to JSON" do
125
+ json = @object.to_jiak
126
+ json.should eql @core_json
127
+
128
+ parsed = JSON.parse(json)
129
+ parsed['bucket'].should eql @bucket_name
130
+ parsed['key'].should eql @key
131
+ parsed['object']['f1'].should eql @data.f1
132
+ parsed['object']['f2'].should eql @data.f2
133
+ parsed['object']['f3']['f3_1'].should eql @data.f3[:f3_1]
134
+ @links.each_with_index do |link,ndx|
135
+ parsed['links'][ndx].should eql link.for_jiak
136
+ end
137
+ end
138
+
139
+ it "should allow attribute updates" do
140
+ bucket_name = 'new bucket'
141
+ bucket = JiakBucket.new(bucket_name,DataObject)
142
+ @object.bucket = bucket
143
+ @object.bucket.should eql bucket
144
+
145
+ key = 'new key'
146
+ @object.key = key
147
+ @object.key.should eql key
148
+
149
+ object = DataObject.new(:f1 => 'new f1',:f2 => [], :f3 => 6)
150
+ @object.data.should_not eql object
151
+ @object.data = object
152
+ @object.data.should eql object
153
+
154
+ links = [JiakLink.new('c','b','a')]
155
+ @object.links = links
156
+ @object.links.should eql links
157
+
158
+ riak = {:vclock => 'VCLOCK', :vtag => 'VTAG', :lastmod => 'LASTMOD'}
159
+ @object.riak = riak
160
+ @object.riak.should eql riak
161
+
162
+ bad_bucket = lambda {@object.bucket = 'bucket'}
163
+ bad_bucket.should raise_error(JiakObjectException,/Bucket/)
164
+
165
+ bad_key = lambda {@object.key = @bucket}
166
+ bad_key.should raise_error(JiakObjectException,/Key/)
167
+
168
+ bad_object = lambda {@object.data = @bucket}
169
+ bad_object.should raise_error(JiakObjectException,/Data/)
170
+
171
+ bad_links = lambda {@object.links = @bucket}
172
+ bad_links.should raise_error(JiakObjectException,/Links/)
173
+ end
174
+
175
+ it "should add a link" do
176
+ jiak_link = JiakLink.new('a','b','c')
177
+ @object.links.should_not include jiak_link
178
+
179
+ size = @links.size
180
+ @object << jiak_link
181
+ @object.links.should have_exactly(size+1).items
182
+ @object.links.should include jiak_link
183
+ end
184
+
185
+ it "should ignore a duplicate link" do
186
+ size = @object.links.size
187
+ @object << @l1
188
+ @object.links.should have_exactly(size).items
189
+ end
190
+
191
+ it "should chain link adds" do
192
+ size = @object.links.size
193
+ jiak_link = JiakLink.new('a','b','c')
194
+ @object << @l2 << jiak_link
195
+ @object.links.should have_exactly(size+1).items
196
+ end
197
+
198
+ it "should raise exception if adding a non-JiakLink" do
199
+ bad_link = lambda {@object << ['l']}
200
+ bad_link.should raise_error(JiakObjectException,/JiakLink/)
201
+ end
202
+
203
+ it "should eql an equal JiakObject" do
204
+ jobj = JiakObject.new(:bucket => @bucket, :key => @key,
205
+ :data => @data, :links => @links)
206
+ @object.should eql jobj
207
+ @object.should == jobj
208
+ end
209
+
210
+ end