jsl-hashback 0.0.1.2 → 0.0.2.3

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