vuderacha-activekv 0.0.0

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.rdoc ADDED
@@ -0,0 +1,34 @@
1
+ = ActiveKV: Active Key/Value objects
2
+ ActiveKV provides a wrapper around Moneta to allow for active objects that can be
3
+ searched and persisted into configured key value stores. Values are serialised JSON.
4
+
5
+ == Getting Started
6
+ Create an ActiveKV configuration file:
7
+ -- config/kv.yml
8
+ development:
9
+ default:
10
+ driver: memory
11
+ test:
12
+ default:
13
+ driver: memory
14
+
15
+ Initialise the ActiveKV infrastructure:
16
+ require 'activekv'
17
+ ActiveKV::Base.configure('config/kv.yml')
18
+
19
+ Create your ActiveKV object:
20
+ class MyPersistentObj < ActiveKV::Base
21
+ key :name
22
+ attr_accessor :x
23
+ end
24
+
25
+ Store your object:
26
+ o = MyPersistentObj.new
27
+ o.name = "asdasd"
28
+ o.x = 12
29
+ o.save!
30
+
31
+ Load your object:
32
+ r = MyPersistentObj.find("asdasd")
33
+ p r.name
34
+ p r.x
data/Rakefile ADDED
@@ -0,0 +1,66 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all examples"
5
+ Spec::Rake::SpecTask.new('examples') do |t|
6
+ t.spec_opts = ["-cfs"]
7
+ t.spec_files = FileList['spec/**/*.rb']
8
+ end
9
+
10
+ desc "Print specdocs"
11
+ Spec::Rake::SpecTask.new(:doc) do |t|
12
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
13
+ t.spec_files = FileList['spec/*_spec.rb']
14
+ end
15
+
16
+ desc "Generate RCov code coverage report"
17
+ Spec::Rake::SpecTask.new('rcov') do |t|
18
+ t.spec_files = FileList['spec/*_spec.rb']
19
+ t.rcov = true
20
+ t.rcov_opts = ['--exclude', 'examples']
21
+ end
22
+
23
+ task :default => :spec
24
+
25
+ ######################################################
26
+
27
+ require 'rake'
28
+ require 'rake/testtask'
29
+ require 'rake/clean'
30
+ require 'rake/gempackagetask'
31
+ require 'rake/rdoctask'
32
+ require 'fileutils'
33
+ require 'jeweler'
34
+ include FileUtils
35
+ # $:.push File.join(File.dirname(__FILE__), 'lib')
36
+
37
+ begin
38
+ require 'jeweler'
39
+ Jeweler::Tasks.new do |s|
40
+ s.name = "activekv"
41
+ s.summary = "Ruby Active Key/Value Objects."
42
+ s.description = "ActiveKV provides ActiveRecord style data storage for Key/Value stores."
43
+ s.author = "Paul Jones"
44
+ s.email = "pauljones23@gmail.com"
45
+ s.homepage = "http://github.com/vuderacha/activekv/"
46
+
47
+ s.files = %w(Rakefile README.rdoc) + Dir.glob("{bin,lib,spec}/**/*")
48
+ s.require_path = "lib"
49
+ s.add_dependency('activesupport', '>= 2.2.2')
50
+ end
51
+ rescue LoadError
52
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
53
+ end
54
+
55
+ task :test => [ :spec ]
56
+
57
+ Rake::RDocTask.new do |t|
58
+ t.rdoc_dir = 'rdoc'
59
+ t.title = "ActiveKV -- Active Key/Value Objects"
60
+ t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
61
+ t.options << '--charset' << 'utf-8'
62
+ t.rdoc_files.include('README.rdoc')
63
+ t.rdoc_files.include('lib/activekv/*.rb')
64
+ end
65
+
66
+ CLEAN.include [ 'build/*', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log', 'pkg', 'lib/*.bundle', '*.gem', '.config' ]
@@ -0,0 +1,150 @@
1
+ module ActiveKV
2
+ class Base
3
+ # Default the key property and configured state to empty states
4
+ @@configured = nil, false
5
+
6
+ def initialize(config = {})
7
+ apply_hash!(config)
8
+ end
9
+
10
+ # Configures the ActiveKV support with the given configuration file
11
+ def self.configure(config_file)
12
+ # Determine our environment
13
+ env = if defined? RACK_ENV then RACK_ENV else :development end
14
+
15
+ # Load the configuration, and find the appropriate section
16
+ config = YAML::load_file(config_file)
17
+ env_config = config[env.to_s]
18
+ if env_config.nil?
19
+ raise "No configuration found for environment #{env}"
20
+ end
21
+
22
+ # Work through each store
23
+ @@stores = {}
24
+ @@default_store = nil
25
+ env_config.each do |store_name, store_config|
26
+ @@stores[store_name] = load_store(store_name, store_config)
27
+ @@default_store = @@stores[store_name] if @@default_store.nil?
28
+ end
29
+
30
+ # Remember that we're configured
31
+ @@configured = true
32
+ end
33
+
34
+ # Prepares a configuration store based on the given configuration
35
+ def self.load_store(name, config)
36
+ raise "No driver specified in configuration #{store_name}" if config['driver'].nil?
37
+
38
+ # Try to create a store driver
39
+ driver_name = config.delete 'driver'
40
+ require "moneta/#{driver_name}"
41
+ class_name = Moneta.constants.find { |c| c.to_s.downcase == driver_name.gsub(/_/, "").downcase }
42
+ raise "No implementation found for driver #{config['driver']}" if class_name.nil?
43
+ driver_class = Moneta.const_get(class_name)
44
+ driver_class.new transform_hash(config)
45
+ end
46
+
47
+ # Requests that the ActiveKV forget its configuration
48
+ def self.unconfigure!
49
+ @@configured = false
50
+ end
51
+
52
+ class << self # Class Methods
53
+ # Sets the property that will be used to work out the key for the item
54
+ def key(key_prop = nil)
55
+ if key_prop.nil?
56
+ return nil if not defined? @key_prop
57
+ return @key_prop
58
+ end
59
+
60
+ @key_prop = key_prop
61
+ attr_accessor key_prop
62
+ end
63
+
64
+ # Changes the pattern used to build keys
65
+ def key_pattern(pattern = nil)
66
+ if pattern.nil?
67
+ return ":class/:key" if not defined? @key_pattern or @key_pattern.nil?
68
+ return @key_pattern
69
+ end
70
+
71
+ @key_pattern = pattern
72
+ end
73
+
74
+ # Sets the store that is used for instances of this class
75
+ def store(name)
76
+ @store = name
77
+ end
78
+
79
+ # Finds a record with the given key
80
+ def find(key)
81
+ # Create the key and lookup the value
82
+ key_val = create_key key
83
+ found_val = store_instance[key_val]
84
+ return nil if found_val.nil? or found_val == {}
85
+ # Check if result is {}, because the memory implementation returns this as a default value
86
+ # when the real value isn't found
87
+
88
+ # Decode the found value, then apply each property in the JSON to the object
89
+ vals = ActiveSupport::JSON.decode(found_val)
90
+ result = new
91
+ result.apply_hash!(vals)
92
+ result
93
+ end
94
+
95
+ # Creates a store key based on the pattern and provided key
96
+ def create_key(key)
97
+ key_pattern.gsub(':class', self.name).gsub(':key', key)
98
+ end
99
+
100
+ # Retrieves an instance of the store that is used for this class
101
+ def store_instance
102
+ if defined? @store and defined? @@stores[@store] then
103
+ @@stores[@store]
104
+ else
105
+ @@default_store
106
+ end
107
+ end
108
+ end
109
+
110
+ # Saves the record to the appropriate datastore
111
+ def save!
112
+ # Ensure that we have everything we need
113
+ raise NotConfiguredError unless @@configured
114
+ raise NoKeySpecifiedError if self.class.key.nil?
115
+ raise NilKeyError if send(self.class.key).nil?
116
+
117
+ # Transform ourselves to json, and get our key
118
+ new_val = to_json
119
+ key_val = self.class.create_key send(self.class.key)
120
+
121
+ # Retrieve the appropriate store, and save
122
+ self.class.store_instance[key_val] = new_val
123
+ end
124
+
125
+ def apply_hash!(props)
126
+ props.each do |k, v|
127
+ send("#{k}=", v)
128
+ end
129
+ end
130
+
131
+ # Transforms a hash so it also indexes by symbol
132
+ def self.transform_hash h
133
+ result = {}
134
+ h.each do |k,v|
135
+ result_v = if v.is_a? Hash then transform_hash(v) else v end
136
+
137
+ result[k] = result_v
138
+ result[k.to_sym] = result_v
139
+ end
140
+ result
141
+ end
142
+ end
143
+
144
+ class NotConfiguredError < Exception
145
+ end
146
+ class NilKeyError < Exception
147
+ end
148
+ class NoKeySpecifiedError < Exception
149
+ end
150
+ end
data/lib/activekv.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ begin
3
+ require 'moneta'
4
+ rescue LoadError
5
+ puts "You need the moneta gem to use ActiveKV"
6
+ exit
7
+ end
8
+ begin
9
+ require 'active_support'
10
+ rescue LoadError
11
+ puts "You need the ActiveSupport gem to use ActiveKV"
12
+ exit
13
+ end
14
+ require 'activekv/base'
data/spec/base.rb ADDED
@@ -0,0 +1,115 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'activekv'
3
+
4
+ RACK_ENV = :test unless defined? RACK_ENV
5
+
6
+ describe "ActiveKV::Base" do
7
+ before do
8
+ ActiveKV::Base.unconfigure!
9
+ end
10
+
11
+ it "should be inheritable" do
12
+ class InheritanceTest < ActiveKV::Base
13
+ end
14
+ end
15
+
16
+ it "should allow a configuration file to be provided" do
17
+ ActiveKV::Base.configure File.join(File.dirname(__FILE__), 'simple-config.yml')
18
+ end
19
+
20
+ it "should fail to save an object if not configured" do
21
+ class Unconfigured < ActiveKV::Base
22
+ end
23
+
24
+ u = Unconfigured.new
25
+ begin
26
+ u.save!
27
+ raise "Should not have allowed an instance to be saved when not configured"
28
+ rescue ActiveKV::NotConfiguredError
29
+ end
30
+ end
31
+
32
+ it "should make the key available on the class" do
33
+ class WithKeyA < ActiveKV::Base
34
+ key :a
35
+ end
36
+ class WithKeyB < ActiveKV::Base
37
+ key :b
38
+ end
39
+
40
+ WithKeyA.key.should == :a
41
+ WithKeyB.key.should == :b
42
+ end
43
+ end
44
+
45
+ describe "ActiveKV::Base when configured" do
46
+ before do
47
+ ActiveKV::Base.unconfigure!
48
+ ActiveKV::Base.configure File.join(File.dirname(__FILE__), 'simple-config.yml')
49
+ end
50
+
51
+ it "should fail to save an object if no key is specified" do
52
+ class NoKey < ActiveKV::Base
53
+ end
54
+
55
+ u = NoKey.new
56
+ begin
57
+ u.save!
58
+ raise "Should not have allowed an instance to be saved when it does not specify a key"
59
+ rescue ActiveKV::NoKeySpecifiedError
60
+ end
61
+ end
62
+
63
+ it "should fail to save an object if key is nil" do
64
+ class WithKey < ActiveKV::Base
65
+ key :name
66
+ end
67
+
68
+ u = WithKey.new
69
+ begin
70
+ u.save!
71
+ raise "Should not have allowed an instance to be saved when key value is nil"
72
+ rescue ActiveKV::NilKeyError
73
+ end
74
+ end
75
+
76
+ it "should allow an object to be saved if configured and a key is specified" do
77
+ class WithKey < ActiveKV::Base
78
+ key :name
79
+ end
80
+
81
+ u = WithKey.new
82
+ u.name = 'TestName'
83
+ u.save!
84
+ end
85
+
86
+ it "should not find an object that has not been created" do
87
+ class NotFound < ActiveKV::Base
88
+ end
89
+
90
+ NotFound.find('missing').should be_nil
91
+ end
92
+
93
+ it "should find an object that has previously been saved" do
94
+ class Found < ActiveKV::Base
95
+ key :name
96
+ end
97
+
98
+ f = Found.new
99
+ f.name = 'myname'
100
+ f.save!
101
+
102
+ Found.find('myname').name.should == 'myname'
103
+ end
104
+
105
+ it "should allow an object to be created with a hash of parameters" do
106
+ class WithSomeParams < ActiveKV::Base
107
+ key :name
108
+ attr_accessor :another_prop
109
+ end
110
+
111
+ p = WithSomeParams.new :name => 'asr', :another_prop => 'world'
112
+ p.name.should == 'asr'
113
+ p.another_prop.should == 'world'
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ test:
2
+ default:
3
+ driver: memory
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vuderacha-activekv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Jones
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-22 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.2.2
24
+ version:
25
+ description: ActiveKV provides ActiveRecord style data storage for Key/Value stores.
26
+ email: pauljones23@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ files:
34
+ - Rakefile
35
+ - README.rdoc
36
+ - lib/activekv
37
+ - lib/activekv/base.rb
38
+ - lib/activekv.rb
39
+ - spec/base.rb
40
+ - spec/simple-config.yml
41
+ has_rdoc: true
42
+ homepage: http://github.com/vuderacha/activekv/
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --inline-source
46
+ - --charset=UTF-8
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.2.0
65
+ signing_key:
66
+ specification_version: 2
67
+ summary: Ruby Active Key/Value Objects.
68
+ test_files: []
69
+