jsl-hashback 0.0.1.2 → 0.0.2.3

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/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 Justin S. Leitgeb
1
+ Copyright (c) 2009 Justin S. Leitgeb
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -1,7 +1,89 @@
1
1
  = HashBack
2
2
 
3
- Provides a general interface over Moneta which allows namespacing of key values and the requirement of correct
4
- Moneta backend class.
3
+ HashBack is a simple Object-hash mapping (OHM) system for Ruby. It allows for serializable classes to be saved,
4
+ retrieved and deleted from any key-value store supported by {Moneta}[http://github.com/wycats/moneta/tree/master]
5
+ (a unified interface to key-value systems).
6
+
7
+ == Quick Start
8
+
9
+ HashBack is easy to use, so we can jump right in to code using the system.
10
+
11
+ First, install the gem:
12
+
13
+ sudo gem install jsl-hashback
14
+
15
+ Then, in your code you'll want to require 'hashback'. For this example, the object ids that we use will be
16
+ UUIDs created by the assaf-uuid gem, so we'll include that as well.
17
+
18
+ require 'hashback'
19
+ require 'uuid'
20
+
21
+ Below we create a simple class that is serializable to HashBack.
22
+
23
+ class Elephant
24
+ HashBack::Resource.setup(self, :uuid, 'Moneta::Memory')
25
+
26
+ attr_accessor :uuid, :name
27
+
28
+ def initialize(name)
29
+ @name = name
30
+ @uuid = UUID.new.generate
31
+ end
32
+ end
33
+
34
+ You can now start using this class to save, fetch and retrieve elephants as follows:
35
+
36
+ dumbo = Elephant.new('Dumbo')
37
+ dumbo.save
38
+
39
+ To bring Dumbo back as a new elephant:
40
+
41
+ new_dumbo = Elephant.fetch(dumbo.uuid)
42
+
43
+ When you're sick of Dumbo and want to get rid of him:
44
+
45
+ new_dumbo.destroy
46
+
47
+ Note that at this point the data is still available in the instance variables for Dumbo, but the persisted form of him is gone.
48
+
49
+ == Detailed usage
50
+
51
+ Generally, HashBack should work with any class that can be serialized. You can decide which key-value storage system
52
+ to use by passing an appropriate class name to HashBack::Resource.setup. See the Moneta documentation for available backends.
53
+
54
+ You can also pass options to HashBack::Resource which are given directly to the moneta backend during initialization as
55
+ follows:
56
+
57
+ require 'hashback'
58
+
59
+ class Foo
60
+ HashBack::Resource.setup(self, :id, 'Moneta::Memcache', :server => 'localhost:1978')
61
+ end
62
+
63
+ This initializes a class with a backend storage in a Tokyo Tyrant server. The serialized forms of objects that are
64
+ stored will be saved with keys like Foo-object_id. You probably want to use a different id method to customize the id
65
+ that will be used to store these objects.
66
+
67
+ == Discussion
68
+
69
+ Key-value databases are rapidly becoming more popular, and they clearly have several use cases that aren't well
70
+ addressed by existing RDBM systems. While adoptation of these key-value storage systems has been rapid, there don't
71
+ seem to be any systems that help to implement common patterns for accessing objects saved in these stores. Before
72
+ writing this program, I couldn't find any precedent for a concept of a OHM (Object Hash Mapping) system, so I put
73
+ together a lightweight implementation with methods for saving and accessing similar to popular ORM systems in Ruby.
74
+
75
+ == TODO
76
+
77
+ The following features are not present in the current library, but may be useful:
78
+
79
+ * A system of callbacks
80
+ * A system for associating objects, perhaps constrained to objects that have a 1 - 1 mapping (since it's not entirely
81
+ intuitive what the structures or algorithms would be for mainting integrity with higher levels of mapping between
82
+ objects).
83
+
84
+ == Feedback
85
+
86
+ Please write the author if you have any questions or feedbacks about this library.
5
87
 
6
88
  == Author
7
89
 
data/hashback.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "hashback"
3
- s.version = "0.0.1.2"
3
+ s.version = "0.0.2.3"
4
4
  s.date = "2009-05-13"
5
5
  s.summary = "Generic tool for writing namespaced key-value data to a variety of hash-type systems"
6
6
  s.email = "justin@phq.org"
@@ -16,13 +16,25 @@ Gem::Specification.new do |s|
16
16
  "README.rdoc",
17
17
  "Rakefile",
18
18
  "lib/hashback.rb",
19
- "lib/hashback/backend.rb"
19
+ "lib/hashback/backend.rb",
20
+ "lib/hashback/resource.rb"
20
21
  ]
21
22
  s.test_files = [
22
23
  "spec/hashback/backend_spec.rb",
23
24
  "spec/hashback_spec.rb",
24
25
  "spec/spec_helper.rb"
25
26
  ]
26
- s.add_dependency("wycats-moneta", ["> 0.0.0"])
27
- s.add_dependency("activesupport", ["> 0.0.0"])
27
+
28
+ s.extra_rdoc_files = [ "README.rdoc" ]
29
+
30
+ s.rdoc_options += [
31
+ '--title', 'HashBack',
32
+ '--main', 'README.rdoc',
33
+ '--line-numbers',
34
+ '--inline-source'
35
+ ]
36
+
37
+ s.add_dependency("wycats-moneta")
38
+ s.add_dependency("activesupport")
39
+ s.add_dependency("assaf-uuid")
28
40
  end
data/lib/hashback.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'moneta'
2
2
  require 'activesupport'
3
3
 
4
- require File.expand_path(File.join(File.dirname(__FILE__), %w[hashback backend] ))
4
+ Dir[File.join(File.dirname(__FILE__), 'hashback', '*.rb')].each do |f|
5
+ require File.expand_path(f)
6
+ end
@@ -8,7 +8,7 @@ module HashBack
8
8
  def initialize(namespace, moneta_klass, options = { })
9
9
  @namespace = namespace
10
10
  @options = options
11
- @moneta = initialize_moneta_klass(moneta_klass)
11
+ @moneta = initialize_moneta_klass(moneta_klass)
12
12
  end
13
13
 
14
14
  def [](key)
@@ -36,7 +36,13 @@ module HashBack
36
36
 
37
37
  def load_moneta_klass(klass)
38
38
  klass_const = klass.respond_to?(:constantize) ? klass.constantize : klass
39
- klass_const.new(@options)
39
+ moneta = klass_const.new(@options)
40
+
41
+ # The options hash would have messed up default Hash initialization to return an empty hash
42
+ # when the key was not found. Revert this case by setting the default to nil if the object
43
+ # responds to this method.
44
+ moneta.default = nil if moneta.respond_to?(:default)
45
+ moneta
40
46
  end
41
47
 
42
48
  def require_klass(klass)
@@ -0,0 +1,56 @@
1
+ module HashBack
2
+
3
+ # HashBack::Resource is an Object-Hash Mapping (OHM) tool for Ruby. It is able to map Ruby objects
4
+ # to any of the backends supported by Moneta, a unified interface to key-value storage systems.
5
+ class Resource
6
+
7
+ # Configures the persistent backend for this object. Configuration options:
8
+ #
9
+ # * +source+ - the class to be persisted
10
+ # * +key_method+ - a symbol representing the method that will return a unique identifier
11
+ # for this object when called on the instance
12
+ # * +moneta_klass+ - a String representation or class constant of the Moneta class used to store this object
13
+ # * +moneta_options+ - an (optional) hash which is passed directly to the moneta backend for configuration
14
+ def self.setup(source, key_method_sym, moneta_klass, moneta_options = {})
15
+ source.__send__(:class_variable_set, :@@_backend, HashBack::Backend.new(source.to_s, moneta_klass, moneta_options))
16
+ source.__send__(:class_variable_set, :@@_key_method_sym, key_method_sym)
17
+
18
+ source.__send__(:include, InstanceMethods)
19
+ source.extend(ClassMethods)
20
+ end
21
+
22
+ module InstanceMethods
23
+
24
+ # Saves the serialized form of this object to the configured backend store.
25
+ def save
26
+ _hashback_backend[_hashback_id_key] = self
27
+ end
28
+
29
+ # Destroy the persisted copy of this object.
30
+ def destroy
31
+ _hashback_backend.delete(_hashback_id_key)
32
+ end
33
+
34
+ ## Methods we try to hide, because we're just sneaky like that.
35
+
36
+ def _hashback_backend
37
+ self.class.__send__(:class_variable_get, :@@_backend)
38
+ end
39
+
40
+ def _hashback_id_key
41
+ self.__send__(self.class.__send__(:class_variable_get, :@@_key_method_sym))
42
+ end
43
+
44
+ private :_hashback_backend, :_hashback_id_key
45
+ end
46
+
47
+ module ClassMethods
48
+
49
+ # Fetches the object identified by +key+ from the storage backend.
50
+ def fetch(key)
51
+ backend = self.__send__(:class_variable_get, :@@_backend)
52
+ backend[key]
53
+ end
54
+ end
55
+ end
56
+ end
@@ -3,6 +3,7 @@ require File.join(File.dirname(__FILE__), %w[ .. spec_helper ])
3
3
  describe HashBack::Backend do
4
4
  before do
5
5
  @mock_moneta = mock('moneta')
6
+ @mock_moneta.stubs(:keys).returns(['keyname'])
6
7
  @moneta_klass = "Moneta::Memory"
7
8
  @b = HashBack::Backend.new('foo', @moneta_klass, { })
8
9
  @b.instance_variable_set(:@moneta, @mock_moneta)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsl-hashback
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.2
4
+ version: 0.0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Leitgeb
@@ -18,9 +18,9 @@ dependencies:
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - ">"
21
+ - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.0.0
23
+ version: "0"
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
@@ -28,9 +28,19 @@ dependencies:
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.0
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: assaf-uuid
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
34
44
  version:
35
45
  description: Wrapper around Moneta that facilitates using the key-value store as a backend for applications requiring namespacing
36
46
  email: justin@phq.org
@@ -38,8 +48,8 @@ executables: []
38
48
 
39
49
  extensions: []
40
50
 
41
- extra_rdoc_files: []
42
-
51
+ extra_rdoc_files:
52
+ - README.rdoc
43
53
  files:
44
54
  - Rakefile
45
55
  - hashback.gemspec
@@ -48,11 +58,17 @@ files:
48
58
  - README.rdoc
49
59
  - lib/hashback.rb
50
60
  - lib/hashback/backend.rb
61
+ - lib/hashback/resource.rb
51
62
  has_rdoc: true
52
63
  homepage: http://github.com/jsl/hashback
53
64
  post_install_message:
54
- rdoc_options: []
55
-
65
+ rdoc_options:
66
+ - --title
67
+ - HashBack
68
+ - --main
69
+ - README.rdoc
70
+ - --line-numbers
71
+ - --inline-source
56
72
  require_paths:
57
73
  - lib
58
74
  required_ruby_version: !ruby/object:Gem::Requirement