perpetuity-memory 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 477ff7a61d0901f4163007a2ee9e5a045ebde5ba
4
+ data.tar.gz: 828e190b7a625cea3dca6e437cb9fda1eb31a323
5
+ SHA512:
6
+ metadata.gz: f0142345ad6aa81ba1974efeeaa838f203799a969432ec8b6c749f2010396987e00a54b3b662bd89ddb08a3826b34c7deabfb0ed7fc99a201361b0d13f544a1d
7
+ data.tar.gz: 2df7c8961a04c70041710d9ace2c70d743648f7bdf8e0a2f399ca6c1ca9e5255a07b0186a6d601c57cb991f403f4c56cef1be2a61d4390ad678a8e8b19505527
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in the perpetuity-memory.gemspec file.
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jamie Gaskins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Perpetuity::Memory
2
+
3
+ This is the in-memory adapter for Perpetuity.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'perpetuity-memory'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install perpetuity-memory
18
+
19
+ ## Usage
20
+
21
+ Put this at the top of your application (or in a Rails initializer):
22
+
23
+ ```ruby
24
+ require 'perpetuity/memory' # Unnecessary if using Rails
25
+ Perpetuity.data_source :memory
26
+ ```
27
+
28
+ For information on using Perpetuity to persist your Ruby objects, see the [main Perpetuity repo](https://github.com/jgaskins/perpetuity).
29
+
30
+ ## Contributing
31
+
32
+ 1. Fork it
33
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
34
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
35
+ 4. Push to the branch (`git push origin my-new-feature`)
36
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ module Perpetuity
2
+ module Memory
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,131 @@
1
+ require 'perpetuity'
2
+ require 'perpetuity/exceptions/duplicate_key_error'
3
+ require 'perpetuity/attribute'
4
+ require 'set'
5
+ require 'securerandom'
6
+
7
+ module Perpetuity
8
+ class Memory
9
+ def initialize options = {}
10
+ @cache = Hash.new
11
+ @indexes = Hash.new { |hash, key| hash[key] = active_indexes(key) }
12
+ end
13
+
14
+ def insert klass, attributes, _
15
+ if attributes.is_a? Array
16
+ return attributes.map{|attr| insert(klass, attr, _)}
17
+ end
18
+
19
+ unless attributes.has_key? :id
20
+ attributes[:id] = SecureRandom.uuid
21
+ end
22
+
23
+ # make keys indifferent
24
+ attributes.default_proc = proc do |h, k|
25
+ case k
26
+ when String then sym = k.to_sym; h[sym] if h.key?(sym)
27
+ when Symbol then str = k.to_s; h[str] if h.key?(str)
28
+ end
29
+ end
30
+
31
+ collection(klass) << attributes
32
+ attributes[:id]
33
+ end
34
+
35
+ def count klass, criteria=nil, &block
36
+ if block_given?
37
+ collection(klass).select(&block).size
38
+ elsif criteria
39
+ collection(klass).select(&criteria).size
40
+ else
41
+ collection(klass).size
42
+ end
43
+ end
44
+
45
+ def delete_all klass
46
+ collection(klass).clear
47
+ end
48
+
49
+ def first klass
50
+ collection(klass).first
51
+ end
52
+
53
+ def find klass, id
54
+ collection(klass).find{|o| o[:id] = id}
55
+ end
56
+
57
+ def retrieve klass, criteria, options = {}
58
+ collection(klass).find_all(&criteria)
59
+ end
60
+
61
+ def all klass
62
+ collection(klass)
63
+ end
64
+
65
+ def delete object, klass=nil
66
+ klass ||= object.class
67
+ id = object.class == String || !object.respond_to?(:id) ? object : object.id
68
+
69
+ collection(klass).each_with_index do |record, index|
70
+ if record[:id] === id
71
+ collection(klass).delete_at index
72
+ end
73
+ end
74
+ end
75
+
76
+ def update klass, id, new_data
77
+ collection(klass).each_with_index do |record, index|
78
+ if record[:id] == id
79
+ collection(klass)[index] = record.merge(new_data)
80
+ end
81
+ end
82
+ end
83
+
84
+ def increment klass, id, attribute, count=1
85
+ find(klass, id)[attribute] += count
86
+ end
87
+
88
+ def can_serialize? value
89
+ true
90
+ end
91
+
92
+ def serialize object, mapper
93
+ Marshal.dump(object)
94
+ end
95
+
96
+ def unserialize data, mapper
97
+ Marshal.load(data)
98
+ end
99
+
100
+
101
+ def index klass, attribute, options={}
102
+ @indexes[klass] ||= Set.new
103
+ end
104
+
105
+ def indexes klass
106
+ @indexes[klass]
107
+ end
108
+
109
+ def active_indexes klass
110
+ Set.new
111
+ end
112
+
113
+ def activate_index! klass
114
+ true
115
+ end
116
+
117
+ def remove_index index
118
+ end
119
+
120
+ def query &block
121
+ block
122
+ end
123
+
124
+ protected
125
+
126
+ def collection klass
127
+ @cache[klass] = Array.new unless @cache.key? klass
128
+ @cache[klass]
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'perpetuity/memory/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "perpetuity-memory"
8
+ spec.version = Perpetuity::Memory::VERSION
9
+ spec.authors = ["Jamie Gaskins", "Christopher Garvis", "Craig Buchek"]
10
+ spec.email = ["craig@boochtek.com"]
11
+ spec.description = %q{In-memory adapter for Perpetuity}
12
+ spec.summary = %q{In-memory adapter for Perpetuity}
13
+ spec.homepage = "https://github.com/boochtek/perpetuity-memory"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_runtime_dependency "perpetuity", "~> 1.0.0.beta3"
25
+ end
@@ -0,0 +1,82 @@
1
+ require 'perpetuity/memory'
2
+ require 'date'
3
+
4
+ module Perpetuity
5
+ describe Memory do
6
+ let(:klass) { String }
7
+
8
+ it 'inserts' do
9
+ expect { subject.insert klass, { name: 'foo' }, [] }.to change { subject.count klass }.by 1
10
+ end
11
+
12
+ it 'inserts multiple objects' do
13
+ expect { subject.insert klass, [{name: 'foo'}, {name: 'bar'}], [] }
14
+ .to change { subject.count klass }.by 2
15
+ end
16
+
17
+ it 'removes all objects' do
18
+ subject.insert klass, {}, []
19
+ subject.delete_all klass
20
+ subject.count(klass).should == 0
21
+ end
22
+
23
+ it 'counts the number of objects' do
24
+ subject.delete_all klass
25
+ 3.times do
26
+ subject.insert klass, {}, []
27
+ end
28
+ subject.count(klass).should == 3
29
+ end
30
+
31
+ it 'counts the objects matching a query' do
32
+ subject.delete_all klass
33
+ 1.times { subject.insert klass, { name: 'bar' }, [] }
34
+ 3.times { subject.insert klass, { name: 'foo' }, [] }
35
+ subject.count(klass) { |o| o[:name] == 'foo' }.should == 3
36
+ end
37
+
38
+ it 'gets the first object' do
39
+ value = {value: 1}
40
+ subject.insert klass, value, []
41
+ subject.first(klass)[:value].should == value['value']
42
+ end
43
+
44
+ it 'gets all objects' do
45
+ values = [{value: 1}, {value: 2}]
46
+ subject.insert klass, values, []
47
+ subject.all(klass).should == values
48
+ end
49
+
50
+ it 'retrieves by ID if the ID is a string' do
51
+ time = Time.now.utc
52
+ id = subject.insert Object, {inserted: time}, []
53
+
54
+ object = subject.retrieve(Object, subject.query{|o| o[:id] == id.to_s }).first
55
+ retrieved_time = object["inserted"]
56
+ retrieved_time.to_f.should be_within(0.001).of time.to_f
57
+ end
58
+
59
+ describe 'serialization' do
60
+ end
61
+
62
+ describe 'indexing' do
63
+ it 'does nothing' do
64
+ subject.index(klass, 'anything')
65
+ end
66
+ end
67
+
68
+ describe 'atomic operations' do
69
+ after(:all) { subject.delete_all klass }
70
+
71
+ it 'increments the value of an attribute' do
72
+ id = subject.insert klass, { count: 1 }, []
73
+ subject.increment klass, id, :count
74
+ subject.increment klass, id, :count, 10
75
+ query = subject.query { |o| o[:id] == id }
76
+ subject.retrieve(klass, query).first['count'].should be == 12
77
+ subject.increment klass, id, :count, -1
78
+ subject.retrieve(klass, query).first['count'].should be == 11
79
+ end
80
+ end
81
+ end
82
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perpetuity-memory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jamie Gaskins
8
+ - Christopher Garvis
9
+ - Craig Buchek
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-01-11 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '1.3'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rake
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: perpetuity
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: 1.0.0.beta3
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: 1.0.0.beta3
71
+ description: In-memory adapter for Perpetuity
72
+ email:
73
+ - craig@boochtek.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - .gitignore
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/perpetuity/memory.rb
84
+ - lib/perpetuity/memory/version.rb
85
+ - perpetuity-memory.gemspec
86
+ - spec/perpetuity/memory_spec.rb
87
+ homepage: https://github.com/boochtek/perpetuity-memory
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.0.14
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: In-memory adapter for Perpetuity
111
+ test_files:
112
+ - spec/perpetuity/memory_spec.rb