riakrest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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