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
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2009-10-20
2
+
3
+ * Initial release:
4
+ * Still pre-alpha
data/Manifest.txt ADDED
@@ -0,0 +1,41 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ examples/auto_update_data.rb
7
+ examples/auto_update_links.rb
8
+ examples/basic_client.rb
9
+ examples/basic_resource.rb
10
+ examples/json_data_resource.rb
11
+ examples/linked_resource.rb
12
+ examples/multiple_resources.rb
13
+ lib/riakrest.rb
14
+ lib/riakrest/core/exceptions.rb
15
+ lib/riakrest/core/jiak_bucket.rb
16
+ lib/riakrest/core/jiak_client.rb
17
+ lib/riakrest/core/jiak_data.rb
18
+ lib/riakrest/core/jiak_link.rb
19
+ lib/riakrest/core/jiak_object.rb
20
+ lib/riakrest/core/jiak_schema.rb
21
+ lib/riakrest/core/query_link.rb
22
+ lib/riakrest/data/jiak_data_hash.rb
23
+ lib/riakrest/resource/jiak_resource.rb
24
+ lib/riakrest/version.rb
25
+ riakrest.gemspec
26
+ script/console
27
+ script/destroy
28
+ script/generate
29
+ spec/core/exceptions_spec.rb
30
+ spec/core/jiak_bucket_spec.rb
31
+ spec/core/jiak_client_spec.rb
32
+ spec/core/jiak_link_spec.rb
33
+ spec/core/jiak_object_spec.rb
34
+ spec/core/jiak_schema_spec.rb
35
+ spec/core/query_link_spec.rb
36
+ spec/data/jiak_data_hash_spec.rb
37
+ spec/resource/jiak_resource_spec.rb
38
+ spec/riakrest_spec.rb
39
+ spec/spec.opts
40
+ spec/spec_helper.rb
41
+ tasks/rspec.rake
data/PostInstall.txt ADDED
@@ -0,0 +1,2 @@
1
+
2
+ For more information on riakrest, see http://gemcutter.org/dingosky/riakrest
data/README.rdoc ADDED
@@ -0,0 +1,51 @@
1
+ = riakrest
2
+
3
+ http://github.com/wcpr/riakrest
4
+
5
+ == DESCRIPTION:
6
+
7
+ RiakRest provides structured, RESTful interaction with a Riak document
8
+ store. In Riak parlance, this JSON data exchange is called Jiak. RiakRest
9
+ provides two levels of interaction: Core Client and Resource. Core Client
10
+ interaction works down at the Jiak level and exposes Jiak internals. Resource
11
+ interaction is an abstraction built on top of the Core Client.
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+
16
+ == SYNOPSIS:
17
+
18
+
19
+ == REQUIREMENTS:
20
+
21
+ RestClient is used for REST server interaction.
22
+ JSON is used for data exchange.
23
+
24
+ == INSTALL:
25
+
26
+ sudo gem install riakrest
27
+
28
+ == LICENSE:
29
+
30
+ (The MIT License)
31
+
32
+ Copyright (c) 2009 Paul Rogers, DingoSky LLC
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining
35
+ a copy of this software and associated documentation files (the
36
+ 'Software'), to deal in the Software without restriction, including
37
+ without limitation the rights to use, copy, modify, merge, publish,
38
+ distribute, sublicense, and/or sell copies of the Software, and to
39
+ permit persons to whom the Software is furnished to do so, subject to
40
+ the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be
43
+ included in all copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
46
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
48
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
50
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
51
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/riakrest'
6
+
7
+ Hoe.plugin :newgem
8
+
9
+ # Generate all the Rake tasks
10
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
11
+ $hoe = Hoe.spec 'riakrest' do
12
+ self.developer 'Paul Rogers', 'paul@dingosky.com'
13
+ self.post_install_message = 'PostInstall.txt'
14
+ self.rubyforge_name = self.name # TODO this is default value
15
+ # self.extra_deps = [['activesupport','>= 2.0.2']]
16
+
17
+ end
18
+
19
+ require 'newgem/tasks'
20
+ Dir['tasks/**/*.rake'].each { |t| load t }
21
+
22
+ # TODO - want other tests/tasks run by default? Add them to the list
23
+ # remove_task :default
24
+ # task :default => [:spec, :features]
@@ -0,0 +1,50 @@
1
+ require 'lib/riakrest'
2
+ include RiakRest
3
+
4
+ PersonData = JiakDataHash.create(:name,:age)
5
+ PersonData.keygen :name
6
+
7
+ class Person
8
+ include JiakResource
9
+
10
+ server 'http://localhost:8002/jiak'
11
+ group 'people'
12
+ data_class PersonData
13
+ auto_post true
14
+ end
15
+
16
+ remy = Person.new(:name => 'remy', :age => 10)
17
+ puts Person.get('remy').name # => "remy"
18
+
19
+ remy.name = "Remy"
20
+ puts Person.get('remy').name # => "remy"
21
+ remy.update
22
+ puts Person.get('remy').name # => "Remy"
23
+
24
+ Person.auto_update true
25
+
26
+ puts Person.get('remy').age # => 10
27
+ remy.age = 12
28
+ puts Person.get('remy').age # => 12
29
+
30
+ Person.auto_update false
31
+ remy.auto_update = true
32
+ puts Person.get('remy').age # => 12
33
+ remy.age = 10
34
+ puts Person.get('remy').age # => 10
35
+
36
+ Person.auto_update true
37
+ remy.auto_update = false
38
+ remy.age = 12
39
+ puts Person.get('remy').age # => 10
40
+ remy.update
41
+ puts Person.get('remy').age # => 12
42
+
43
+ remy.auto_update = nil
44
+ remy.age = 10
45
+ puts Person.get('remy').age # => 10
46
+
47
+ remy.delete
48
+ callie.delete
49
+
50
+
@@ -0,0 +1,48 @@
1
+ require 'lib/riakrest'
2
+ include RiakRest
3
+
4
+ PersonData = JiakDataHash.create(:name,:age)
5
+ PersonData.keygen :name
6
+
7
+ class Person
8
+ include JiakResource
9
+
10
+ server 'http://localhost:8002/jiak'
11
+ group 'people'
12
+ data_class PersonData
13
+ auto_post true
14
+ end
15
+
16
+ remy = Person.new(:name => 'remy', :age => 10)
17
+ callie = Person.new(:name => 'Callie', :age => 12)
18
+
19
+ remy.link(callie,'sister')
20
+ puts remy.walk(Person,'sister').size # => 0
21
+ remy.update
22
+ puts remy.walk(Person,'sister').size # => 1
23
+ remy.remove_link(callie,'sister')
24
+
25
+ Person.auto_update true
26
+ remy.link(callie,'sibling')
27
+ puts remy.walk(Person,'sibling').size # => 1
28
+ remy.remove_link(callie,'sibling')
29
+
30
+ callie.auto_update = false
31
+ callie.link(remy,'sibling')
32
+ puts callie.walk(Person,'sibling').size # => 0
33
+ callie.update
34
+ puts callie.walk(Person,'sibling').size # => 1
35
+ callie.remove_link(remy,'sibling')
36
+
37
+ Person.auto_update false
38
+ remy.auto_update = true
39
+ callie.auto_update = nil
40
+ remy.bi_link(callie,'sisters')
41
+ puts remy.walk(Person,'sisters').size # => 1
42
+ puts callie.walk(Person,'sisters').size # => 0
43
+ callie.update
44
+ puts callie.walk(Person,'sisters').size # => 1
45
+
46
+ remy.delete
47
+ callie.delete
48
+
@@ -0,0 +1,33 @@
1
+ require 'lib/riakrest'
2
+ include RiakRest
3
+
4
+ Person = JiakDataHash.create(:name,:age)
5
+
6
+ client = JiakClient.new("http://localhost:8002/jiak")
7
+ bucket = JiakBucket.new('people',Person)
8
+ client.set_schema(bucket)
9
+
10
+ remy = client.store(JiakObject.new(:bucket => bucket,
11
+ :data => Person.new(:name => "remy",
12
+ :age => 10)),
13
+ :object => true)
14
+ puts client.get(bucket,remy.key).data.name # => "remy"
15
+
16
+ remy.data.name # => "remy"
17
+ remy.data.name = "Remy"
18
+ client.store(remy)
19
+ puts client.get(bucket,remy.key).data.name # => "Remy"
20
+
21
+
22
+ callie = client.store(JiakObject.new(:bucket => bucket,
23
+ :data => Person.new(:name => "Callie",
24
+ :age => 12)),
25
+ :object => true)
26
+ remy << JiakLink.new(bucket,callie.key,'sister')
27
+ client.store(remy)
28
+
29
+ sisters = client.walk(bucket,remy.key,QueryLink.new(bucket,'sister'),Person)
30
+ sisters[0].eql?(callie) # => true
31
+
32
+ client.delete(bucket,remy.key)
33
+ client.delete(bucket,callie.key)
@@ -0,0 +1,34 @@
1
+ require 'lib/riakrest'
2
+ include RiakRest
3
+
4
+ PersonData = JiakDataHash.create(:name,:age)
5
+ PersonData.keygen :name
6
+
7
+ class Person
8
+ include JiakResource
9
+
10
+ server 'http://localhost:8002/jiak'
11
+ group 'people'
12
+ data_class PersonData
13
+ auto_post true
14
+ end
15
+
16
+ remy = Person.new(:name => 'remy', :age => 10)
17
+ puts Person.get('remy').name # => "remy"
18
+
19
+ remy.name = "Remy"
20
+ remy.update
21
+ puts remy.name # => "Remy"
22
+ puts Person.get('remy').name # => "Remy"
23
+
24
+ callie = Person.new(:name => 'Callie', :age => 12)
25
+ remy.bi_link(callie,'sister').update
26
+ callie.update
27
+
28
+ sisters = remy.walk(Person,'sister')
29
+ puts sisters[0].eql?(callie) # => true
30
+
31
+ remy.delete
32
+ callie.delete
33
+
34
+
@@ -0,0 +1,32 @@
1
+ require 'date'
2
+ class DogData # :nodoc:
3
+ include JiakData
4
+
5
+ allowed :name, :birthdate, :weight, :breed
6
+ readwrite :name, :birthdate, :weight
7
+
8
+ def initialize(hsh)
9
+ hsh.each {|key,val| send("#{key}=",val)}
10
+ end
11
+
12
+ def self.create(hsh)
13
+ new(hsh)
14
+ end
15
+
16
+ def self.jiak_create(jiak)
17
+ jiak['birthdate'] = Date.parse(jiak['birthdate']) if jiak['birthdate']
18
+ new(jiak)
19
+ end
20
+
21
+ def for_jiak
22
+ self.class.write_mask.inject({}) do |build,field|
23
+ val = send("#{field}")
24
+ build[field] = val unless val.nil?
25
+ build
26
+ end
27
+ end
28
+
29
+ def keygen
30
+ @name
31
+ end
32
+ end
@@ -0,0 +1,113 @@
1
+ require 'lib/riakrest'
2
+ include RiakRest
3
+
4
+ PersonData = JiakDataHash.create(:name)
5
+ PersonData.keygen :name
6
+
7
+ class Parent
8
+ include JiakResource
9
+
10
+ server 'http://localhost:8002/jiak'
11
+ group 'parents'
12
+ data_class PersonData
13
+ end
14
+
15
+ Child = Parent.copy(:group => 'children')
16
+
17
+ # relationships
18
+ parent_children = {
19
+ 'p0' => ['c0'],
20
+ 'p1' => ['c0','c1','c2'],
21
+ 'p2' => ['c2','c3'],
22
+ 'p3' => ['c3']
23
+ }
24
+
25
+ # invert relationships
26
+ child_parents = parent_children.inject({}) do |build, (p,cs)|
27
+ cs.each do |c|
28
+ build[c] ? build[c] << p : build[c] = [p]
29
+ end
30
+ build
31
+ end
32
+
33
+ # store data and relationships
34
+ parent_children.each do |pname,cnames|
35
+ p = Parent.new(:name => pname)
36
+ cnames.each do |cname|
37
+ begin
38
+ c = Child.get(cname)
39
+ rescue
40
+ c = Child.new(:name => cname)
41
+ end
42
+ c.link(p,'parent')
43
+ c.put
44
+ p.link(c,'child')
45
+ end
46
+ p.post
47
+ end
48
+
49
+ # retrieve parents
50
+ parents = parent_children.keys.map {|p| Parent.get(p)}
51
+ p0,p1,p2,p3 = parents
52
+ p1.name # => 'p1'
53
+
54
+ # retrieve children
55
+ children = child_parents.keys.map {|c| Child.get(c)}
56
+ c0,c1,c2,c3 = children
57
+ c1.name # => 'c1'
58
+
59
+ # retrieve parent children
60
+ p0c,p1c,p2c,p3c = parents.map {|p| p.walk(Child,'child')}
61
+ p2c[0].name # => 'c2' (not sorted, so could be 'c3')
62
+
63
+ # retrieve children parents
64
+ c0p,c1p,c2p,c3p = children.map {|c| c.walk(Parent,'parent')}
65
+ c3p[0].name # => 'p3'
66
+
67
+ # retrieve children siblings
68
+ c0s,c1s,c2s,c3s = children.map do |c|
69
+ c.walk(Parent,'parent',Child,'child').delete_if{|s| s.eql?(c)}
70
+ end
71
+ c3s[0].name # => 'c2'
72
+
73
+ # who is c3's step-sibling's other parent?
74
+ c3sp = c3.walk(Parent,'parent',Child,'child',Parent,'parent')
75
+ c3p.each {|p| c3sp.delete_if{|sp| p.eql?(sp)}}
76
+ c3sp[0].name # => "p1"
77
+
78
+ # add sibling links
79
+ children.each do |c|
80
+ siblings = c.walk(Parent,'parent',Child,'child').delete_if{|s| s.eql?(c)}
81
+ siblings.each {|s| c.link(s,'sibling')}
82
+ c.update
83
+ end
84
+ c1.walk(Child,'sibling').size # => 2
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+ # some folks are odd, and others are normal
94
+ parent_children.keys.each do |p|
95
+ parent = Parent.get(p)
96
+ p_children = parent.walk(Child,'child')
97
+ p_children.each do |child|
98
+ child.link(parent, p[1].to_i.odd? ? 'odd' : 'normal')
99
+ child.update
100
+ parent.link(child, child.name[1].to_i.odd? ? 'odd' : 'normal')
101
+ end
102
+ parent.update
103
+ end
104
+ # refresh parents and children variables
105
+ parents.each {|p| p.get}
106
+ children.each {|c| c.get}
107
+
108
+ # do any odd parents have normal children?
109
+ op = parents.inject([]) do |build,parent|
110
+ build << parent.walk(Child,'normal',Parent,'odd')
111
+ build.flatten.uniq
112
+ end
113
+ op[0].name # => 'p1'
@@ -0,0 +1,43 @@
1
+ require 'lib/riakrest'
2
+ include RiakRest
3
+
4
+ DogData = JiakDataHash.create(:name,:weight,:breed)
5
+ DogData.keygen :name
6
+ class Dog
7
+ include JiakResource
8
+ server 'http://localhost:8002/jiak'
9
+ group 'dogs'
10
+ data_class DogData
11
+ end
12
+
13
+ DogBreedData = JiakDataHash.create(DogData.schema)
14
+ DogBreedData.readwrite :name, :breed
15
+ DogBreed = Dog.copy(:data_class => DogBreedData)
16
+
17
+ DogWeightData = JiakDataHash.create(DogData.schema)
18
+ DogWeightData.readwrite :name, :weight
19
+ DogWeight = Dog.copy(:data_class => DogWeightData)
20
+
21
+ Dog.pov
22
+ addie = Dog.new(:name => 'adelaide', :weight => 45, :breed => 'heeler')
23
+ addie.post
24
+ puts addie.name # => "adelaide"
25
+ puts addie.breed # => "heeler"
26
+ puts addie.weight # => 45
27
+
28
+ DogBreed.pov
29
+ addie = DogBreed.get('adelaide')
30
+ addie.breed = "Heeler"
31
+ addie.put
32
+
33
+ DogWeight.pov
34
+ addie = DogWeight.get('adelaide')
35
+ addie.weight = 47
36
+ addie.put
37
+
38
+ Dog.pov
39
+ addie = Dog.get('adelaide')
40
+ puts addie.name # => "adelaide"
41
+ puts addie.breed # => "Heeler"
42
+ puts addie.weight # => 47
43
+
@@ -0,0 +1,73 @@
1
+ module RiakRest
2
+
3
+ # Top-level RiakRest exception. All RiakRest exceptions are subclass of this
4
+ # class.
5
+ class Exception < StandardError
6
+ end
7
+
8
+ # Client exception in accessing a resource on the Jiak server.
9
+ class JiakResourceException < RiakRest::Exception
10
+ attr_accessor :params
11
+
12
+ # call-seq:
13
+ # raise JiakClientException, message="", params={}
14
+ #
15
+ # The message is handled using normal Ruby exception handling. The params
16
+ # field is a hash containing:
17
+ # <code>action</code>:: The client resource access action.
18
+ # <code>args</code>:: The arguments to the action.
19
+ # <code>uri</code>:: The URI used to access the resource.
20
+ def initialize(msg="", params={})
21
+ super(msg)
22
+ @params = params
23
+ end
24
+
25
+ # call-seq:
26
+ # err.description -> string
27
+ #
28
+ # A string description of a client error when accessing a Jiak resource.
29
+ def description
30
+ unless(@params.empty?)
31
+ action = @params[:action] || ""
32
+ args = @params[:args] || "()"
33
+ uri = @params[:uri] || ""
34
+ "#{self.class}: #{action}#{args} #{message} using uri='#{uri}'"
35
+ else
36
+ "#{self.class}: #{message}"
37
+ end
38
+ end
39
+ end
40
+
41
+ # Exceptions pertaining to JiakClient usage.
42
+ class JiakClientException < RiakRest::Exception
43
+ end
44
+
45
+ # Resource not found on the Jiak server.
46
+ class JiakResourceNotFound < RiakRest::JiakResourceException
47
+ end
48
+
49
+ # Exceptions pertaining to JiakBucket usage.
50
+ class JiakBucketException < RiakRest::Exception
51
+ end
52
+
53
+ # Exceptions pertaining to JiakObject usage.
54
+ class JiakObjectException < RiakRest::Exception
55
+ end
56
+
57
+ # Exceptions pertaining to JiakData usage.
58
+ class JiakDataException < RiakRest::Exception
59
+ end
60
+
61
+ # Exceptions pertaining to JiakLink usage.
62
+ class JiakLinkException < RiakRest::Exception
63
+ end
64
+
65
+ # Exceptions pertaining to JiakSchema usage.
66
+ class JiakSchemaException < RiakRest::Exception
67
+ end
68
+
69
+ # Exceptions pertaining to QueryLink usage.
70
+ class QueryLinkException < RiakRest::Exception
71
+ end
72
+
73
+ end