riakrest 0.0.1 → 0.0.2
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 +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
|