the-blob 0.0.1 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/handlers/instance_handler.rb +20 -56
- data/lib/persisters/memory_persister.rb +91 -0
- data/lib/the_blob.rb +3 -2
- data/lib/the_blob/instance.rb +39 -3
- metadata +10 -5
- data/lib/handlers/link_handler.rb +0 -25
- data/lib/the_blob/instance_methods.rb +0 -31
@@ -2,69 +2,33 @@ require File.expand_path '../../the_blob/instance', __FILE__
|
|
2
2
|
|
3
3
|
module InstanceHandler
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
#TODO move this into seperate class
|
10
|
-
def load_instances
|
11
|
-
dir = File.expand_path("app/instances", ".")
|
12
|
-
Dir["#{dir}/*"].each do |file|
|
13
|
-
puts file
|
14
|
-
require file
|
15
|
-
create_methods(file)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def create_methods(file)
|
20
|
-
klass = file.scan(/\/([^\/]+)\.rb/).first.first
|
21
|
-
make_class_getter(klass)
|
22
|
-
make_index_getters(klass)
|
23
|
-
end
|
24
|
-
|
25
|
-
def make_class_getter(klass)
|
26
|
-
class_eval <<-CODE
|
27
|
-
def #{klass}s
|
28
|
-
instance_lists["#{klass.capitalize}"]
|
29
|
-
end
|
30
|
-
CODE
|
31
|
-
end
|
32
|
-
|
33
|
-
def make_index_getters(klass)
|
34
|
-
Module.const_get(klass.capitalize).get_instance_indices.each do |index|
|
35
|
-
class_eval <<-CODE
|
36
|
-
def emit_#{klass}_by_#{index}(id)
|
37
|
-
instance = instances["#{klass.capitalize}"]["__#{index}"][id]
|
38
|
-
instance || raise(InstanceNotFound)
|
39
|
-
end
|
40
|
-
CODE
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.included(base)
|
47
|
-
base.extend(ClassMethods)
|
48
|
-
base.load_instances
|
5
|
+
def initialize(options = {memory: MemoryPersister})
|
6
|
+
load_instances
|
7
|
+
@memory_persister = options[:memory].new(@klass_list)
|
49
8
|
end
|
50
9
|
|
51
10
|
def absorb(instance)
|
52
|
-
|
53
|
-
instance_lists[klass.to_s] << instance
|
54
|
-
klass.get_instance_indices.each do |index|
|
55
|
-
instances[klass.to_s]["__#{index}"][instance.send(index)] = instance
|
56
|
-
end
|
11
|
+
@memory_persister.absorb instance
|
57
12
|
end
|
58
13
|
|
59
14
|
private
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
15
|
+
def load_instances
|
16
|
+
dir = File.expand_path("app/instances", ".")
|
17
|
+
Dir["#{dir}/*"].each do |file|
|
18
|
+
require file
|
19
|
+
klass = Module.const_get file.scan(/\/([^\/]+)\.rb/).first.first.capitalize
|
20
|
+
make_index_getters(klass)
|
21
|
+
(@klass_list ||= []) << klass
|
22
|
+
end
|
64
23
|
end
|
65
24
|
|
66
|
-
def
|
67
|
-
|
25
|
+
def make_index_getters(klass)
|
26
|
+
klass.get_instance_indices.each do |index|
|
27
|
+
instance_eval <<-CODE
|
28
|
+
def emit_#{klass.underscore}_by_#{index}(id)
|
29
|
+
@memory_persister.emit_#{klass.underscore}_by_#{index}(id)
|
30
|
+
end
|
31
|
+
CODE
|
32
|
+
end
|
68
33
|
end
|
69
|
-
|
70
34
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
class MemoryPersister
|
2
|
+
|
3
|
+
class Full < RuntimeError; end
|
4
|
+
|
5
|
+
def initialize(klass_list, options = {})
|
6
|
+
klass_list.each{ |klass| make_index_getters(klass) }
|
7
|
+
sub_capacity = (options[:capacity] || 100000) / 2
|
8
|
+
@new_container = MemoryContainer.new klass_list, capacity: sub_capacity
|
9
|
+
@old_container = MemoryContainer.new klass_list, capacity: sub_capacity
|
10
|
+
end
|
11
|
+
|
12
|
+
def absorb(instance)
|
13
|
+
@new_container.absorb instance
|
14
|
+
rescue MemoryPersister::Full
|
15
|
+
rotate_containers
|
16
|
+
absorb instance
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def rotate_containers
|
21
|
+
@old_container.clear
|
22
|
+
p = @new_container
|
23
|
+
@new_container = @old_container
|
24
|
+
@old_container = p
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_index_getters(klass)
|
28
|
+
klass.get_instance_indices.each do |index|
|
29
|
+
instance_eval <<-CODE
|
30
|
+
def emit_#{klass.underscore}_by_#{index}(id)
|
31
|
+
@new_container.emit_#{klass.underscore}_by_#{index} id
|
32
|
+
rescue TheBlob::InstanceNotFound
|
33
|
+
instance = @old_container.emit_#{klass.underscore}_by_#{index} id
|
34
|
+
@new_container.absorb instance
|
35
|
+
instance
|
36
|
+
end
|
37
|
+
CODE
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
class MemoryPersister::MemoryContainer
|
44
|
+
|
45
|
+
def initialize(klass_list, options = {})
|
46
|
+
klass_list.each {|klass| make_index_getters klass }
|
47
|
+
@capacity = options[:capacity] || 65535
|
48
|
+
clear
|
49
|
+
end
|
50
|
+
|
51
|
+
def absorb(instance)
|
52
|
+
raise MemoryPersister::Full if self.capacity_left <= 0
|
53
|
+
klass = instance.class
|
54
|
+
klass.get_instance_indices.each do |index|
|
55
|
+
instances[klass.to_s]["__#{index}"][instance.send(index)] = instance
|
56
|
+
end
|
57
|
+
@capacity_used += 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def capacity_left
|
61
|
+
@capacity - @capacity_used
|
62
|
+
end
|
63
|
+
|
64
|
+
def clear
|
65
|
+
@instances = new_instances_hash
|
66
|
+
@capacity_used = 0
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def make_index_getters(klass)
|
72
|
+
klass.get_instance_indices.each do |index|
|
73
|
+
instance_eval <<-CODE
|
74
|
+
def emit_#{klass.underscore}_by_#{index}(id)
|
75
|
+
instance = instances["#{klass}"]["__#{index}"][id]
|
76
|
+
instance && instance.dup || raise(TheBlob::InstanceNotFound)
|
77
|
+
end
|
78
|
+
CODE
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def instances
|
83
|
+
@instances
|
84
|
+
end
|
85
|
+
|
86
|
+
def new_instances_hash
|
87
|
+
hash = proc{|a| Hash.new{|hash, key| hash[key] = a} }
|
88
|
+
hash.call( hash.call( hash.call( nil )))
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/lib/the_blob.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require File.expand_path '../handlers/instance_handler', __FILE__
|
2
|
-
require File.expand_path '../
|
2
|
+
require File.expand_path '../persisters/memory_persister', __FILE__
|
3
3
|
|
4
4
|
module TheBlob
|
5
5
|
|
6
|
+
class InstanceNotFound < RuntimeError; end
|
7
|
+
|
6
8
|
def self.included(base)
|
7
9
|
base.class_eval do
|
8
|
-
include LinkHandler
|
9
10
|
include InstanceHandler
|
10
11
|
end
|
11
12
|
end
|
data/lib/the_blob/instance.rb
CHANGED
@@ -1,7 +1,43 @@
|
|
1
|
-
|
1
|
+
module Instance
|
2
2
|
|
3
|
-
|
3
|
+
def self.included(base)
|
4
|
+
base.instance_eval do
|
5
|
+
def self.underscore
|
6
|
+
self.to_s.gsub(/::/, '/').
|
7
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
8
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
9
|
+
tr("-", "_").
|
10
|
+
downcase
|
11
|
+
end
|
4
12
|
|
5
|
-
|
13
|
+
def self.get_next_id
|
14
|
+
@next_id ||= 0
|
15
|
+
@next_id += 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.instance_indices(*ind)
|
19
|
+
indices = ind << :id
|
20
|
+
attr_accessor *indices
|
21
|
+
@instance_indices = indices
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get_instance_indices
|
25
|
+
@instance_indices ||= []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(attrs = {})
|
31
|
+
@id = self.class.get_next_id
|
32
|
+
attrs.each{ |name, value| name.inspect; send("#{name}=", value) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def id
|
36
|
+
@id
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(instance_2)
|
40
|
+
self.class == instance_2.class && id == instance_2.id
|
41
|
+
end
|
6
42
|
|
7
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: the-blob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.21
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,15 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-14 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: The blob
|
14
|
+
description: ! 'The blob is an instance handling interface that seperates ORM responsibilities
|
15
|
+
from application instances.
|
16
|
+
|
17
|
+
This allows for fast and easy testing of your application by not needing to load
|
18
|
+
ORM code in your business logic.
|
19
|
+
|
20
|
+
'
|
15
21
|
email: kwstannard@gmail.com
|
16
22
|
executables: []
|
17
23
|
extensions: []
|
@@ -19,9 +25,8 @@ extra_rdoc_files: []
|
|
19
25
|
files:
|
20
26
|
- lib/the_blob.rb
|
21
27
|
- lib/handlers/instance_handler.rb
|
22
|
-
- lib/
|
28
|
+
- lib/persisters/memory_persister.rb
|
23
29
|
- lib/the_blob/instance.rb
|
24
|
-
- lib/the_blob/instance_methods.rb
|
25
30
|
homepage: https://github.com/kwstannard/the_blob
|
26
31
|
licenses: []
|
27
32
|
post_install_message:
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module LinkHandler
|
2
|
-
|
3
|
-
def create_link (instance_1, instance_2)
|
4
|
-
links[instance_1][instance_2.class] << instance_2
|
5
|
-
links[instance_2][instance_1.class] << instance_1
|
6
|
-
nil
|
7
|
-
end
|
8
|
-
|
9
|
-
def delete_link(instance_1, instance_2)
|
10
|
-
links[instance_1][instance_2.class].delete(instance_2)
|
11
|
-
links[instance_2][instance_1.class].delete(instance_1)
|
12
|
-
nil
|
13
|
-
end
|
14
|
-
|
15
|
-
def get_links(instance, klass)
|
16
|
-
links[instance][klass].dup
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def links
|
22
|
-
@links ||= Hash.new{|hash, key| hash[key] = Hash.new{|hash, key| hash[key] = []} }
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module InstanceMethods
|
2
|
-
|
3
|
-
def self.included(base)
|
4
|
-
base.instance_eval do
|
5
|
-
def self.get_next_id
|
6
|
-
@next_id ||= 0
|
7
|
-
@next_id += 1
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.instance_indices(*ind)
|
11
|
-
indices = ind << :id
|
12
|
-
attr_accessor *indices
|
13
|
-
@instance_indices = indices
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.get_instance_indices
|
17
|
-
@instance_indices ||= []
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def initialize(attrs = {})
|
23
|
-
@id = self.class.get_next_id
|
24
|
-
attrs.each{ |name, value| name.inspect; send("#{name}=", value) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def id
|
28
|
-
@id
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|