ropl 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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