ropl 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/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Ropl
2
2
 
3
- TODO: Write a gem description
3
+ There are plenty of ORMs out there. With a K/V database like Riak,
4
+ having an ORM means an awkward fit, since Riak doesn't natively
5
+ have any way to represent a Relationship.
6
+
7
+ In a conversation with Nathan Aschbacher, it was pointed out that
8
+ all we really want in many cases is persistence. So here it is --
9
+ a stupidly simple Riak Object Persistence Layer. ROPL.
4
10
 
5
11
  ## Installation
6
12
 
@@ -18,7 +24,8 @@ Or install it yourself as:
18
24
 
19
25
  ## Usage
20
26
 
21
- TODO: Write usage instructions here
27
+ Take a look at test/test_composition_story.rb and test/test_oop_story.rb
28
+ The later is the preferred usage.
22
29
 
23
30
  ## Contributing
24
31
 
data/Rakefile CHANGED
@@ -4,7 +4,6 @@ require "bundler/gem_tasks"
4
4
  require 'rubygems'
5
5
  gem 'bundler'
6
6
  require 'bundler'
7
- require 'ripple'
8
7
 
9
8
  begin
10
9
  Bundler.setup(:default, :development)
@@ -1,5 +1,29 @@
1
- require "ropl/version"
1
+ require 'riak'
2
+ require 'ropl/composition'
2
3
 
3
4
  module Ropl
4
- # Your code goes here...
5
+ class Ropl
6
+ def initialize(riak_client)
7
+ @riak_client = riak_client
8
+ end
9
+
10
+ def post(object)
11
+ robject = Riak::RObject.new @riak_client.bucket(object.class.name)
12
+ robject.content_type = 'application/x-marshalled-ruby-object'
13
+ robject.raw_data = Marshal::dump(object)
14
+ robject.store
15
+ end
16
+
17
+ def put(object, key)
18
+ robject = Riak::RObject.new @riak_client.bucket(object.class.name), key.to_s
19
+ robject.content_type = 'application/x-marshalled-ruby-object'
20
+ robject.raw_data = Marshal::dump(object)
21
+ robject.store.key
22
+ end
23
+
24
+ def get(klass, key)
25
+ robject = @riak_client.bucket(klass.name).get(key.to_s)
26
+ Marshal::load(robject.raw_data)
27
+ end
28
+ end
5
29
  end
@@ -0,0 +1,36 @@
1
+ module Ropl
2
+ module Composition
3
+ class Error < StandardError; end
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ attr_accessor :ropl, :key
10
+
11
+ def persist
12
+ ropl = self.class.class_variable_get :@@ropl_object
13
+
14
+ raise Error if ropl.nil?
15
+
16
+ if @key.nil?
17
+ @key = ropl.post self
18
+ else
19
+ ropl.put self, @key
20
+ end
21
+ @key
22
+ end
23
+
24
+ module ClassMethods
25
+ def ropl(riak_client)
26
+ self.ancestors[0].class_variable_set :@@ropl_object, Ropl.new(riak_client)
27
+ end
28
+
29
+ def retrieve(key)
30
+ ropl = self.ancestors[0].class_variable_get :@@ropl_object
31
+ raise Error if ropl.nil?
32
+ ropl.get self.ancestors[0], key
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module Ropl
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
6
6
  gem.email = ["clr@port49.com"]
7
7
  gem.description = %q{Riak Object Persistence Layer}
8
8
  gem.summary = %q{Why bother with an ORM? Just store the object. This is OOP, after all.}
9
- gem.homepage = ""
9
+ gem.homepage = "https://github.com/clr/ropl"
10
10
 
11
11
  gem.add_dependency "riak-client", "~> 1.0.0"
12
12
 
@@ -0,0 +1,5 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'test/unit'
5
+ require File.join('lib','ropl')
@@ -0,0 +1,9 @@
1
+ :development:
2
+ :host: 127.0.0.1
3
+ :pb_port: 8081
4
+ :protocol: pbc
5
+
6
+ :test:
7
+ :host: 127.0.0.1
8
+ :pb_port: 8081
9
+ :protocol: pbc
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.join('..','helper'), __FILE__)
2
+
3
+ class CompositeClass
4
+ include Ropl::Composition
5
+ attr_accessor :attribute_one, :attribute_two
6
+
7
+ def initialize(attribute_one, attribute_two)
8
+ @attribute_one = attribute_one
9
+ @attribute_two = attribute_two
10
+ end
11
+ end
12
+
13
+ class TestCompositeClass < Test::Unit::TestCase
14
+ def setup
15
+ riak_config = YAML.load(File.read(File.expand_path(File.join('..','riak.yml'), __FILE__)))[:test]
16
+ riak_client = Riak::Client.new riak_config
17
+ # set the persistence connection
18
+ CompositeClass.ropl riak_client
19
+ end
20
+
21
+ def test_post
22
+ # create some object without specifying the key
23
+ composite_class = CompositeClass.new 'post data', 'other post data'
24
+
25
+ # save it
26
+ assert composite_class.persist
27
+ assert !composite_class.key.nil?
28
+ end
29
+
30
+ def test_put
31
+ # create some object with a key
32
+ composite_class = CompositeClass.new 'put data', 'other put data'
33
+
34
+ # set the key
35
+ composite_class.key = 'put key'
36
+
37
+ # save it
38
+ response = composite_class.persist
39
+ assert 'put key', response
40
+ end
41
+
42
+ def test_put_then_get
43
+ # create some object with a key
44
+ composite_class = CompositeClass.new 'put data', 'other put data'
45
+ composite_class.key = 'put key'
46
+
47
+ # save it
48
+ composite_class.persist
49
+
50
+ # get the object back
51
+ composite_class = CompositeClass.retrieve 'put key'
52
+
53
+ assert_equal 'put data', composite_class.attribute_one
54
+ assert_equal 'other put data', composite_class.attribute_two
55
+ end
56
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.join('..','helper'), __FILE__)
2
+
3
+ class Animal
4
+ include Ropl::Composition
5
+
6
+ attr_accessor :type, :friends, :interests
7
+ end
8
+
9
+ class TestCompositionStory < Test::Unit::TestCase
10
+ def test_story
11
+ # set up Riak connection
12
+ riak_config = YAML.load(File.read(File.expand_path(File.join('..','riak.yml'), __FILE__)))[:test]
13
+ riak_client = Riak::Client.new riak_config
14
+
15
+ henry = Animal.new
16
+ henry.key = 'henry'
17
+ henry.type = :chicken
18
+ henry.friends = 12
19
+ henry.interests = ["walking in the woods", "eating berries"]
20
+
21
+ timothy = Animal.new
22
+ timothy.key = 'timothy'
23
+ timothy.type = :bovine
24
+ timothy.friends = 17
25
+ timothy.interests = ["walking in fields of grass", "eating berries", "hanging out with the family"]
26
+
27
+ # ... later on that evening,
28
+ # we decide that henry and timothy
29
+ # are worth keeping around
30
+
31
+ Animal.ropl riak_client
32
+
33
+ henry.persist
34
+ timothy.persist
35
+
36
+ # ... and then some time later,
37
+ # perhaps in a different context,
38
+ # we want to compare interests
39
+
40
+ henry = Animal.retrieve 'henry'
41
+ timothy = Animal.retrieve 'timothy'
42
+
43
+ assert_equal ["eating berries"], henry.interests & timothy.interests
44
+ end
45
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.join('..','helper'), __FILE__)
2
+
3
+ class Animal
4
+ attr_accessor :type, :friends, :interests
5
+ end
6
+
7
+ class TestOopStory < Test::Unit::TestCase
8
+ def test_story
9
+ # set up Riak connection and persistence object
10
+ riak_config = YAML.load(File.read(File.expand_path(File.join('..','riak.yml'), __FILE__)))[:test]
11
+ riak_client = Riak::Client.new riak_config
12
+ ropl = Ropl::Ropl.new riak_client
13
+
14
+ # go about your day
15
+ henry = Animal.new
16
+ henry.type = :chicken
17
+ henry.friends = 12
18
+ henry.interests = ["walking in the woods", "eating berries"]
19
+
20
+ timothy = Animal.new
21
+ timothy.type = :bovine
22
+ timothy.friends = 17
23
+ timothy.interests = ["walking in fields of grass", "eating berries", "hanging out with the family"]
24
+
25
+ # later on that evening,
26
+ # we decide that henry and timothy
27
+ # are worth keeping around
28
+
29
+ ropl.put henry, :henry
30
+ ropl.put timothy, :timothy
31
+
32
+ # then some time even later,
33
+ # perhaps in a different context,
34
+ # we want to compare interests
35
+
36
+ henry = ropl.get Animal, :henry
37
+ timothy = ropl.get Animal, :timothy
38
+
39
+ assert_equal ["eating berries"], henry.interests & timothy.interests
40
+ end
41
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.join('..','helper'), __FILE__)
2
+
3
+ class PersistedClass
4
+ attr_accessor :attribute_one, :attribute_two
5
+ end
6
+
7
+ class TestPersistedClass < Test::Unit::TestCase
8
+ def setup
9
+ riak_config = YAML.load(File.read(File.expand_path(File.join('..','riak.yml'), __FILE__)))[:test]
10
+ riak_client = Riak::Client.new riak_config
11
+ @ropl = Ropl::Ropl.new riak_client
12
+ end
13
+
14
+ def test_post
15
+ # create some object without a key
16
+ persisted_class = PersistedClass.new
17
+ persisted_class.attribute_one = 'post data'
18
+ persisted_class.attribute_two = 'other post data'
19
+
20
+ # save it
21
+ response = @ropl.post persisted_class
22
+ assert response
23
+ end
24
+
25
+ def test_put
26
+ # create some object with a key
27
+ persisted_class = PersistedClass.new
28
+ persisted_class.attribute_one = 'put data'
29
+ persisted_class.attribute_two = 'other put data'
30
+
31
+ # save it
32
+ response = @ropl.put persisted_class, 'put key'
33
+ assert_equal 'put key', response
34
+ end
35
+
36
+ def test_put_then_get
37
+ # create some object with a key
38
+ persisted_class = PersistedClass.new
39
+ persisted_class.attribute_one = 'put data'
40
+ persisted_class.attribute_two = 'other put data'
41
+
42
+ # save it
43
+ @ropl.put persisted_class, 'put key'
44
+
45
+ # get the object back
46
+ persisted_class = @ropl.get PersistedClass, 'put key'
47
+ assert_equal 'put data', persisted_class.attribute_one
48
+ assert_equal 'other put data', persisted_class.attribute_two
49
+ end
50
+
51
+ =begin
52
+ def test_a_thousand_ops
53
+ # create a thousand objects
54
+ objects = 1000.times.map do
55
+ random_ascii = lambda{|n| rand(n).times.map{rand(256).chr}.join}
56
+
57
+ # create some object with a key
58
+ persisted_class = PersistedClass.new
59
+ persisted_class.attribute_one = random_ascii.call(1000)
60
+ persisted_class.attribute_two = random_ascii.call(1000)
61
+
62
+ [persisted_class, random_ascii.call(20)]
63
+ end
64
+
65
+ # persist each object
66
+ start_time = Time.now
67
+ objects.each do |object|
68
+ # save it
69
+ @ropl.put *object
70
+ end
71
+ puts "\nOne thousand ops time elapsed: #{Time.now - start_time} seconds.\n"
72
+ end
73
+ =end
74
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ropl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-20 00:00:00.000000000 Z
12
+ date: 2013-02-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: riak-client
16
- requirement: &70174493876300 !ruby/object:Gem::Requirement
16
+ requirement: &70098053914280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 1.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70174493876300
24
+ version_requirements: *70098053914280
25
25
  description: Riak Object Persistence Layer
26
26
  email:
27
27
  - clr@port49.com
@@ -35,9 +35,16 @@ files:
35
35
  - README.md
36
36
  - Rakefile
37
37
  - lib/ropl.rb
38
+ - lib/ropl/composition.rb
38
39
  - lib/ropl/version.rb
39
40
  - ropl.gemspec
40
- homepage: ''
41
+ - test/helper.rb
42
+ - test/riak.yml
43
+ - test/test_composition.rb
44
+ - test/test_composition_story.rb
45
+ - test/test_oop_story.rb
46
+ - test/test_persisted_class.rb
47
+ homepage: https://github.com/clr/ropl
41
48
  licenses: []
42
49
  post_install_message:
43
50
  rdoc_options: []
@@ -61,4 +68,10 @@ rubygems_version: 1.8.15
61
68
  signing_key:
62
69
  specification_version: 3
63
70
  summary: Why bother with an ORM? Just store the object. This is OOP, after all.
64
- test_files: []
71
+ test_files:
72
+ - test/helper.rb
73
+ - test/riak.yml
74
+ - test/test_composition.rb
75
+ - test/test_composition_story.rb
76
+ - test/test_oop_story.rb
77
+ - test/test_persisted_class.rb