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.
- data/History.txt +4 -0
- data/Manifest.txt +41 -0
- data/PostInstall.txt +2 -0
- data/README.rdoc +51 -0
- data/Rakefile +24 -0
- data/examples/auto_update_data.rb +50 -0
- data/examples/auto_update_links.rb +48 -0
- data/examples/basic_client.rb +33 -0
- data/examples/basic_resource.rb +34 -0
- data/examples/json_data_resource.rb +32 -0
- data/examples/linked_resource.rb +113 -0
- data/examples/multiple_resources.rb +43 -0
- data/lib/riakrest/core/exceptions.rb +73 -0
- data/lib/riakrest/core/jiak_bucket.rb +146 -0
- data/lib/riakrest/core/jiak_client.rb +316 -0
- data/lib/riakrest/core/jiak_data.rb +265 -0
- data/lib/riakrest/core/jiak_link.rb +131 -0
- data/lib/riakrest/core/jiak_object.rb +233 -0
- data/lib/riakrest/core/jiak_schema.rb +242 -0
- data/lib/riakrest/core/query_link.rb +156 -0
- data/lib/riakrest/data/jiak_data_hash.rb +182 -0
- data/lib/riakrest/resource/jiak_resource.rb +628 -0
- data/lib/riakrest/version.rb +7 -0
- data/lib/riakrest.rb +164 -0
- data/riakrest.gemspec +38 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/core/exceptions_spec.rb +18 -0
- data/spec/core/jiak_bucket_spec.rb +103 -0
- data/spec/core/jiak_client_spec.rb +358 -0
- data/spec/core/jiak_link_spec.rb +77 -0
- data/spec/core/jiak_object_spec.rb +210 -0
- data/spec/core/jiak_schema_spec.rb +184 -0
- data/spec/core/query_link_spec.rb +128 -0
- data/spec/data/jiak_data_hash_spec.rb +14 -0
- data/spec/resource/jiak_resource_spec.rb +128 -0
- data/spec/riakrest_spec.rb +17 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +12 -0
- data/tasks/rspec.rake +21 -0
- 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
|