riakrest 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/History.txt +4 -1
- data/LICENSE +22 -0
- data/README.rdoc +52 -26
- data/Rakefile +55 -24
- data/VERSION +1 -0
- data/examples/auto_update_data.rb +1 -7
- data/examples/auto_update_links.rb +8 -8
- data/examples/basic_client.rb +8 -10
- data/examples/basic_resource.rb +16 -18
- data/examples/json_data_resource.rb +5 -0
- data/examples/linked_resource.rb +32 -27
- data/examples/links_only.rb +38 -0
- data/lib/riakrest/core/jiak_client.rb +5 -0
- data/lib/riakrest/core/jiak_data.rb +19 -13
- data/lib/riakrest/core/query_link.rb +1 -1
- data/lib/riakrest/resource/jiak_resource.rb +135 -54
- data/lib/riakrest/version.rb +1 -1
- data/lib/riakrest.rb +33 -30
- data/spec/resource/jiak_resource_spec.rb +388 -34
- metadata +56 -29
- data/Manifest.txt +0 -41
- data/PostInstall.txt +0 -2
- data/riakrest.gemspec +0 -38
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/tasks/rspec.rake +0 -21
@@ -86,14 +86,12 @@ module RiakRest
|
|
86
86
|
|
87
87
|
klass.schema.allowed_fields.each do |field|
|
88
88
|
define_method("#{field}=") do |val|
|
89
|
-
@jiak.
|
90
|
-
|
91
|
-
|
92
|
-
self.class.put(self)
|
93
|
-
end
|
89
|
+
@jiak.object.data.send("#{field}=",val)
|
90
|
+
self.class.do_auto_update(self)
|
91
|
+
val
|
94
92
|
end
|
95
93
|
define_method("#{field}") do
|
96
|
-
@jiak.
|
94
|
+
@jiak.object.data.send("#{field}")
|
97
95
|
end
|
98
96
|
end
|
99
97
|
end
|
@@ -273,7 +271,8 @@ module RiakRest
|
|
273
271
|
# general the values set on the Riak cluster should suffice.
|
274
272
|
def put(resource,opts={})
|
275
273
|
opts[:object] = true
|
276
|
-
resource.jiak.
|
274
|
+
resource.jiak.object = jiak.server.store(resource.jiak.object,opts)
|
275
|
+
resource.convenient_jiak
|
277
276
|
resource
|
278
277
|
end
|
279
278
|
|
@@ -284,7 +283,7 @@ module RiakRest
|
|
284
283
|
# resource has not been previously stored. See JiakResource#put for
|
285
284
|
# options.
|
286
285
|
def post(resource,opts={})
|
287
|
-
unless(resource.
|
286
|
+
unless(resource.local?)
|
288
287
|
raise JiakResourceException, "Resource already initially stored"
|
289
288
|
end
|
290
289
|
put(resource,opts)
|
@@ -296,7 +295,7 @@ module RiakRest
|
|
296
295
|
# Updates a JiakResource on the Jiak server with a guard to ensure the
|
297
296
|
# resource has been previously stored. See JiakResource#put for options.
|
298
297
|
def update(resource,opts={})
|
299
|
-
if(resource.
|
298
|
+
if(resource.local?)
|
300
299
|
raise JiakResourceException, "Resource not previously stored"
|
301
300
|
end
|
302
301
|
put(resource,opts)
|
@@ -311,6 +310,9 @@ module RiakRest
|
|
311
310
|
# <code>:reads</code> --- The number of Riak nodes that must successfully
|
312
311
|
# reply with the data. If not set, defaults first to the value set for the
|
313
312
|
# JiakResource class, then to the value set on the Riak cluster.
|
313
|
+
#
|
314
|
+
# Raise JiakResourceNotFound if no resource exists on the Jiak server for
|
315
|
+
# the key.
|
314
316
|
def get(key,opts={})
|
315
317
|
new(jiak.server.get(jiak.bucket,key,opts))
|
316
318
|
end
|
@@ -322,7 +324,7 @@ module RiakRest
|
|
322
324
|
# data of the JiakResource is overwritten, so use with caution. See
|
323
325
|
# JiakResource.get for options.
|
324
326
|
def refresh(resource,opts={})
|
325
|
-
resource.jiak.
|
327
|
+
resource.jiak.object = get(resource.jiak.key,opts).jiak.object
|
326
328
|
end
|
327
329
|
|
328
330
|
# :call-seq:
|
@@ -336,21 +338,34 @@ module RiakRest
|
|
336
338
|
# value set for the JiakResource, then to the value set on the Riak
|
337
339
|
# cluster. In general the values set on the Riak cluster should suffice.
|
338
340
|
def delete(resource,opts={})
|
339
|
-
jiak.server.delete(jiak.bucket,resource.jiak.
|
341
|
+
jiak.server.delete(jiak.bucket,resource.jiak.object.key,opts)
|
340
342
|
end
|
341
343
|
|
342
344
|
# :call-seq:
|
343
345
|
# JiakResource.link(from,to,tag) -> JiakResource
|
344
346
|
#
|
345
347
|
# Link from a resource to another resource by tag.
|
348
|
+
#
|
349
|
+
# Note the resource being linked to cannot be a local object since the
|
350
|
+
# created link needs to include the Jiak server key. Even if a local
|
351
|
+
# object has a local key intended for use as the Jiak server key, there
|
352
|
+
# is no guarentee that key will not already be in use on the Jiak
|
353
|
+
# server. Only after a resource is stored on the Jiak server is the key
|
354
|
+
# assignment guarenteed.
|
355
|
+
#
|
356
|
+
# This restriction is not necessary for the resource being linked from,
|
357
|
+
# since it's Jiak server key is not in play. This does allow for
|
358
|
+
# establishing links to existing Jiak resources locally and storing with
|
359
|
+
# the initial store of the local Jiak resource.
|
346
360
|
def link(from,to,tag)
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
361
|
+
if(to.local?)
|
362
|
+
raise JiakResourceException, "Can't link to a local resource"
|
363
|
+
end
|
364
|
+
|
365
|
+
link = JiakLink.new(to.jiak.object.bucket, to.jiak.object.key, tag)
|
366
|
+
unless from.jiak.object.links.include?(link)
|
367
|
+
from.jiak.object.links << link
|
368
|
+
do_auto_update(from)
|
354
369
|
end
|
355
370
|
from
|
356
371
|
end
|
@@ -370,10 +385,10 @@ module RiakRest
|
|
370
385
|
# :call-seq:
|
371
386
|
# JiakResource.remove_link(from,to,tag) -> true or false
|
372
387
|
def remove_link(from,to,tag)
|
373
|
-
link = JiakLink.new(to.jiak.
|
374
|
-
has_link = from.jiak.
|
388
|
+
link = JiakLink.new(to.jiak.object.bucket, to.jiak.object.key, tag)
|
389
|
+
has_link = from.jiak.object.links.include?(link)
|
375
390
|
if has_link
|
376
|
-
from.jiak.
|
391
|
+
from.jiak.object.links.delete(link)
|
377
392
|
if(from.auto_update? ||
|
378
393
|
((from.auto_update? != false) && from.class.auto_update?))
|
379
394
|
put(from)
|
@@ -383,7 +398,7 @@ module RiakRest
|
|
383
398
|
end
|
384
399
|
|
385
400
|
# :call-seq:
|
386
|
-
# JiakResource.
|
401
|
+
# JiakResource.query(from,*steps)
|
387
402
|
#
|
388
403
|
# Retrieves an array of JiakResource objects by starting with the links
|
389
404
|
# in the <code>from</code> JiakResource and doing the query steps. The
|
@@ -394,10 +409,10 @@ module RiakRest
|
|
394
409
|
#
|
395
410
|
# ====Usage
|
396
411
|
# <code>
|
397
|
-
# JiakResource.
|
398
|
-
# JiakResource.
|
412
|
+
# JiakResource.query(resource,Child,'child')
|
413
|
+
# JiakResource.query(resource,Parent,'odd',Child,'normal')
|
399
414
|
# </code>
|
400
|
-
def
|
415
|
+
def query(from,*steps)
|
401
416
|
links = []
|
402
417
|
until steps.empty?
|
403
418
|
begin
|
@@ -411,22 +426,37 @@ module RiakRest
|
|
411
426
|
end
|
412
427
|
end
|
413
428
|
links = links[0] if links.size == 1
|
414
|
-
jiak.server.walk(from.jiak.
|
429
|
+
jiak.server.walk(from.jiak.object.bucket, from.jiak.object.key, links,
|
415
430
|
last_klass.jiak.bucket.data_class).map do |jobj|
|
416
431
|
last_klass.new(jobj)
|
417
432
|
end
|
418
433
|
end
|
434
|
+
alias :walk :query
|
419
435
|
|
436
|
+
# :call-seq:
|
437
|
+
# JiakResource.exist?(key) -> true or false
|
438
|
+
#
|
439
|
+
# Determine if a resource exists on the Jiak server for a key.
|
440
|
+
def exist?(key)
|
441
|
+
begin
|
442
|
+
get(key)
|
443
|
+
true
|
444
|
+
rescue JiakResourceNotFound
|
445
|
+
false
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
420
449
|
# :call-seq:
|
421
450
|
# copy(opts={}) -> JiakResource
|
422
451
|
#
|
423
452
|
# Copies a JiakResource, resetting values passed as options. Valid
|
424
453
|
# options on copy are those mandatory to create a JiakResource:
|
425
454
|
# <code>:server</code>, <code>:group</code>, and
|
426
|
-
# <code>:data_class</code
|
455
|
+
# <code>:data_class</code>, and optional auto flags
|
456
|
+
# <code>auto_post</code> and <code>auto_update</code>.
|
427
457
|
#
|
428
458
|
def copy(opts={})
|
429
|
-
valid = [:server,:group,:data_class]
|
459
|
+
valid = [:server,:group,:data_class,:auto_post,:auto_update]
|
430
460
|
err = opts.select {|k,v| !valid.include?(k)}
|
431
461
|
unless err.empty?
|
432
462
|
raise JiakResourceException, "unrecognized options: #{err.keys}"
|
@@ -435,11 +465,30 @@ module RiakRest
|
|
435
465
|
opts[:server] ||= jiak.server.uri
|
436
466
|
opts[:group] ||= jiak.bucket.name
|
437
467
|
opts[:data_class] ||= jiak.bucket.data_class
|
468
|
+
opts[:auto_post] ||= auto_post?
|
469
|
+
opts[:auto_update] ||= auto_update?
|
438
470
|
Class.new do
|
439
471
|
include JiakResource
|
440
|
-
server
|
441
|
-
group
|
442
|
-
data_class
|
472
|
+
server opts[:server]
|
473
|
+
group opts[:group]
|
474
|
+
data_class opts[:data_class]
|
475
|
+
auto_post opts[:auto_post]
|
476
|
+
auto_update opts[:auto_update]
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
# :call-seq:
|
481
|
+
# JiakResource.do_auto_update(resource) -> JiakResource or nil
|
482
|
+
#
|
483
|
+
# Determine if an auto update should be done on the resource and perform
|
484
|
+
# an update if so.
|
485
|
+
#
|
486
|
+
# Public method as a by-product of implementation.
|
487
|
+
def do_auto_update(rsrc) # :no-doc:
|
488
|
+
if(!rsrc.local? &&
|
489
|
+
(rsrc.auto_update? ||
|
490
|
+
((rsrc.auto_update? != false) && rsrc.class.auto_update?)))
|
491
|
+
update(rsrc)
|
443
492
|
end
|
444
493
|
end
|
445
494
|
|
@@ -471,18 +520,32 @@ module RiakRest
|
|
471
520
|
# is passed to the <code>new</code> method of the JiakData associated
|
472
521
|
# with the JiakResource.
|
473
522
|
def initialize(*args)
|
474
|
-
# First form is used by JiakResource.get and JiakResource.
|
475
|
-
@jiak = Struct.new(:
|
523
|
+
# First form is used by JiakResource.get and JiakResource.query
|
524
|
+
@jiak = Struct.new(:object,:bucket,:key,:data,:links,:auto_update).new
|
476
525
|
if(args.size == 1 && args[0].is_a?(JiakObject))
|
477
|
-
@jiak.
|
526
|
+
@jiak.object = args[0]
|
478
527
|
else
|
479
528
|
bucket = self.class.jiak.bucket
|
480
|
-
@jiak.
|
481
|
-
|
529
|
+
@jiak.object = JiakObject.new(:bucket => bucket,
|
530
|
+
:data => bucket.data_class.new(*args))
|
482
531
|
if(self.class.auto_post?)
|
532
|
+
if(!@jiak.object.key.empty? && self.class.exist?(@jiak.object.key))
|
533
|
+
raise(JiakResourceException,
|
534
|
+
"auto-post failed: key='#{@jiak.object.key}' already exists.")
|
535
|
+
end
|
483
536
|
self.class.post(self)
|
484
537
|
end
|
485
538
|
end
|
539
|
+
convenient_jiak
|
540
|
+
end
|
541
|
+
|
542
|
+
# Public method as a by-product of implementation. No harm done in calling
|
543
|
+
# this method, as it will just repeat assignments already done.
|
544
|
+
def convenient_jiak # :nodoc:
|
545
|
+
@jiak.bucket = @jiak.object.bucket
|
546
|
+
@jiak.key = @jiak.object.key
|
547
|
+
@jiak.data = @jiak.object.data
|
548
|
+
@jiak.links = @jiak.object.links
|
486
549
|
end
|
487
550
|
|
488
551
|
# :call-seq:
|
@@ -518,7 +581,8 @@ module RiakRest
|
|
518
581
|
# Put this resource on the Jiak server. See JiakResource#ClassMethods#put
|
519
582
|
# for options.
|
520
583
|
def put(opts={})
|
521
|
-
@jiak.
|
584
|
+
@jiak.object = (self.class.put(self,opts)).jiak.object
|
585
|
+
convenient_jiak
|
522
586
|
self
|
523
587
|
end
|
524
588
|
|
@@ -529,7 +593,8 @@ module RiakRest
|
|
529
593
|
# has not been previously stored. See JiakResource#ClassMethods#put for
|
530
594
|
# options.
|
531
595
|
def post(opts={})
|
532
|
-
@jiak.
|
596
|
+
@jiak.object = (self.class.post(self,opts)).jiak.object
|
597
|
+
convenient_jiak
|
533
598
|
self
|
534
599
|
end
|
535
600
|
|
@@ -540,9 +605,11 @@ module RiakRest
|
|
540
605
|
# has been previously stored. See JiakResource#ClassMethods#put for
|
541
606
|
# options.
|
542
607
|
def update(opts={})
|
543
|
-
@jiak.
|
608
|
+
@jiak.object = (self.class.update(self,opts)).jiak.object
|
609
|
+
convenient_jiak
|
544
610
|
self
|
545
611
|
end
|
612
|
+
alias :push :update
|
546
613
|
|
547
614
|
# :call-seq:
|
548
615
|
# refresh(opts={}) -> nil
|
@@ -551,7 +618,18 @@ module RiakRest
|
|
551
618
|
# is overwritten, so use with caution. See JiakResource#ClassMethods#get
|
552
619
|
# for options.
|
553
620
|
def refresh(opts={})
|
554
|
-
self.class.refresh
|
621
|
+
self.class.refresh(self,opts)
|
622
|
+
end
|
623
|
+
alias :pull :refresh
|
624
|
+
|
625
|
+
# :call-seq:
|
626
|
+
# local? -> true or false
|
627
|
+
#
|
628
|
+
# <code>true</code> if a resource is local only, i.e., has not been
|
629
|
+
# post/put to the Jiak server. This test is used in the guards for class
|
630
|
+
# and instance level post/update methods.
|
631
|
+
def local?
|
632
|
+
jiak.object.riak.nil?
|
555
633
|
end
|
556
634
|
|
557
635
|
# :call-seq:
|
@@ -566,7 +644,9 @@ module RiakRest
|
|
566
644
|
# :call-seq:
|
567
645
|
# link(resource,tag) -> JiakResource
|
568
646
|
#
|
569
|
-
# Link to the resource by tag.
|
647
|
+
# Link to the resource by tag. Note the resource being linked to cannot be
|
648
|
+
# local. The object creating this link can be local. See JiakResource#link
|
649
|
+
# for a discussion.
|
570
650
|
def link(resource,tag)
|
571
651
|
self.class.link(self,resource,tag)
|
572
652
|
end
|
@@ -589,39 +669,40 @@ module RiakRest
|
|
589
669
|
end
|
590
670
|
|
591
671
|
# :call-seq:
|
592
|
-
#
|
672
|
+
# query(*steps) -> array
|
593
673
|
#
|
594
|
-
# Performs a Jiak
|
595
|
-
# JiakResource#ClassMethods#
|
674
|
+
# Performs a Jiak query starting at this resource. See
|
675
|
+
# JiakResource#ClassMethods#query for description.
|
596
676
|
#
|
597
677
|
# ====Usage
|
598
678
|
# <code>
|
599
|
-
#
|
600
|
-
#
|
679
|
+
# query(Child,'child')
|
680
|
+
# query(Parent,'odd',Child,'normal')
|
601
681
|
# </code>
|
602
|
-
def
|
603
|
-
self.class.
|
682
|
+
def query(*steps)
|
683
|
+
self.class.query(self,*steps)
|
604
684
|
end
|
685
|
+
alias :walk :query
|
605
686
|
|
606
|
-
# call-seq:
|
607
|
-
#
|
687
|
+
# :call-seq:
|
688
|
+
# jiak_resource == other -> true or false
|
608
689
|
#
|
609
690
|
# Equality -- Two JiakResources are equal if they wrap the same data.
|
610
691
|
def ==(other)
|
611
|
-
(@jiak.
|
692
|
+
(@jiak.object == other.jiak.object) rescue false
|
612
693
|
end
|
613
694
|
|
614
|
-
# call-seq:
|
695
|
+
# :call-seq:
|
615
696
|
# eql?(other) -> true or false
|
616
697
|
#
|
617
698
|
# Returns <code>true</code> if <code>other</code> is a JiakResource
|
618
699
|
# representing the same Jiak data.
|
619
700
|
def eql?(other)
|
620
|
-
other.is_a?(JiakResource) && @jiak.
|
701
|
+
other.is_a?(JiakResource) && @jiak.object.eql?(other.jiak.object)
|
621
702
|
end
|
622
703
|
|
623
704
|
def hash # :nodoc:
|
624
|
-
@jiak.
|
705
|
+
@jiak.object.hash
|
625
706
|
end
|
626
707
|
|
627
708
|
end
|
data/lib/riakrest/version.rb
CHANGED
data/lib/riakrest.rb
CHANGED
@@ -84,7 +84,7 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
84
84
|
# </code>
|
85
85
|
# Now we can get callie as the sister of remy:
|
86
86
|
# <code>
|
87
|
-
# sisters = client.
|
87
|
+
# sisters = client.query(bucket,remy.key,QueryLink.new(bucket,'sister'),Person)
|
88
88
|
# sisters[0].eql?(callie) # => true
|
89
89
|
# </code>
|
90
90
|
# Finally, we'll delete the objects on the way out the door.
|
@@ -99,35 +99,38 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
99
99
|
# create resource objects that encapsulate a lot of the cruft of core client
|
100
100
|
# interaction. We'll do the same steps as above using resources.
|
101
101
|
# <code>
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
102
|
+
# require 'riakrest'
|
103
|
+
# include RiakRest
|
104
|
+
#
|
105
|
+
# PersonData = JiakDataHash.create(:name,:age)
|
106
|
+
# PersonData.keygen :name
|
107
|
+
#
|
108
|
+
# class Person
|
109
|
+
# include JiakResource
|
110
|
+
# server 'http://localhost:8002/jiak'
|
111
|
+
# group 'people'
|
112
|
+
# data_class PersonData
|
113
|
+
# auto_post true
|
114
|
+
# auto_update true
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# remy = Person.new(:name => 'remy',:age => 10) # (auto-post)
|
118
|
+
# puts remy.name # => "remy" (auto-update)
|
119
|
+
#
|
120
|
+
# puts Person.get('remy').name # => "remy" (from Jiak server)
|
121
|
+
# puts Person.get('remy').age # => 10 (from Jiak server)
|
122
|
+
#
|
123
|
+
# remy.age = 11 # (auto-update)
|
124
|
+
# puts Person.get('remy').age # => 11 (from Jiak server)
|
125
|
+
#
|
126
|
+
# callie = Person.new(:name => 'Callie', :age => 13)
|
127
|
+
# remy.link(callie,'sister')
|
128
|
+
#
|
129
|
+
# sisters = remy.query(Person,'sister')
|
130
|
+
# puts sisters[0].eql?(callie) # => true
|
131
|
+
#
|
132
|
+
# remy.delete
|
133
|
+
# callie.delete
|
131
134
|
# </code>
|
132
135
|
# Ah, that feels better. Go forth and Riak!
|
133
136
|
module RiakRest
|