mementus 0.1.1 → 0.1.2
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 +8 -8
- data/README.md +1 -14
- data/lib/mementus/model.rb +56 -20
- data/lib/mementus/version.rb +1 -1
- data/mementus.gemspec +1 -1
- data/spec/collection_spec.rb +13 -1
- data/spec/mapping_spec.rb +4 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
N2I2NmZkNjY1MGMwYWE0ZGI3ZmRmZjY0OGFlODI1YWQyZjhkMTU5OA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NDNhZGVhZjZlMWE5NzJmYmY5YjM0ODIxODA0ZDViZWZiNjZmNGExZg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OWYyMGY5NDc1ODdkNGQ2ZmQ5ZDExZTI2ODA4MjUxZWYyM2RmYmM5NTE3ZTAx
|
10
|
+
NmQ4ODNjZTgxODQyZjdkZjFhYjMzNTQ4YTA2MDQ0YTU4NGY1MjVmMWI2NzZk
|
11
|
+
NTQ4ZjBiNGZmN2I0ODYxN2U2N2RjZDdmZWE3ZTM2YTNhZGJhMGQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTlhZTVmODY1OGQ1MDhmYzU3MWE1NWM0NWUyMmM1MTIwMjY1YmNjZDkyMGJk
|
14
|
+
YzU4MTk2ODA5MGYyMWRlODk4YjZkOGFlZTkzMGNjZGQyNGI3MGI3M2I2NTI4
|
15
|
+
NzFkMGYzNDA1ODFkMTczMGMxOTA0MzdjYTU1MmEwMTI0OTIzMTU=
|
data/README.md
CHANGED
@@ -2,20 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/maetl/mementus)
|
4
4
|
|
5
|
-
|
6
|
-
# Proof of concept for a toy ORM that combines some aspects of the
|
7
|
-
# ActiveRecord API with an in-memory query model based on the Axiom
|
8
|
-
# relational algebra API.
|
9
|
-
#
|
10
|
-
# The weirdest trick is that the data stored in the relational model
|
11
|
-
# is a read-only index that never gets re-materialised back into the
|
12
|
-
# model objects themselves (though Axiom does seem to be capable of
|
13
|
-
# doing this).
|
14
|
-
#
|
15
|
-
# Instead of returning mapped data from queries, the Ruby object_id
|
16
|
-
# is used as a reference to point to the existing instance in the
|
17
|
-
# runtime object space.
|
18
|
-
```
|
5
|
+
Proof of concept for a toy ORM that combines some aspects of the ActiveRecord API with an in-memory query model based on the Axiom relational algebra API.
|
19
6
|
|
20
7
|
## Installation
|
21
8
|
|
data/lib/mementus/model.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'virtus'
|
2
2
|
require 'axiom-memory-adapter'
|
3
|
+
require 'mini_cache'
|
3
4
|
|
4
5
|
module Mementus
|
5
6
|
|
@@ -7,15 +8,6 @@ module Mementus
|
|
7
8
|
# ActiveRecord API with an in-memory query model based on the Axiom
|
8
9
|
# relational algebra API.
|
9
10
|
#
|
10
|
-
# The weirdest trick is that the data stored in the relational model
|
11
|
-
# is a read-only index that never gets re-materialised back into the
|
12
|
-
# model objects themselves (though Axiom does seem to be capable of
|
13
|
-
# doing this).
|
14
|
-
#
|
15
|
-
# Instead of returning mapped data from queries, the Ruby object_id
|
16
|
-
# is used as a reference to point to the existing instance in the
|
17
|
-
# runtime object space.
|
18
|
-
#
|
19
11
|
class Model
|
20
12
|
|
21
13
|
@@local_storage = nil
|
@@ -25,12 +17,18 @@ module Mementus
|
|
25
17
|
name_without_namespace = name.split("::").last
|
26
18
|
name_without_namespace.gsub(/([^\^])([A-Z])/,'\1_\2').downcase.to_sym
|
27
19
|
end
|
20
|
+
|
21
|
+
# Unique cache identifier for this instance
|
22
|
+
#
|
23
|
+
def cache_key
|
24
|
+
"#{self.class.name_to_sym.to_s}-#{object_id.to_s}"
|
25
|
+
end
|
28
26
|
|
29
27
|
# TODO: this mapping could be based on declared indexes,
|
30
28
|
# rather than dumping the entire attribute schema here.
|
31
29
|
#
|
32
30
|
def schema_tuple
|
33
|
-
tuple = [[:
|
31
|
+
tuple = [[:__cache_key, String]]
|
34
32
|
attribute_set.each do |attribute_type|
|
35
33
|
tuple << [attribute_type.name.to_sym, attribute_type.primitive]
|
36
34
|
end
|
@@ -41,7 +39,7 @@ module Mementus
|
|
41
39
|
# rather than dumping the entire attribute data set here.
|
42
40
|
#
|
43
41
|
def values_tuple
|
44
|
-
tuple = [
|
42
|
+
tuple = [cache_key]
|
45
43
|
attributes.each do |_, attribute_value|
|
46
44
|
tuple << attribute_value
|
47
45
|
end
|
@@ -58,6 +56,7 @@ module Mementus
|
|
58
56
|
def create
|
59
57
|
ensure_registered(self)
|
60
58
|
local_storage[self.class.name_to_sym].insert([values_tuple])
|
59
|
+
self.class.cache_put(self.cache_key, self)
|
61
60
|
end
|
62
61
|
|
63
62
|
def ensure_registered(model)
|
@@ -79,27 +78,64 @@ module Mementus
|
|
79
78
|
end
|
80
79
|
|
81
80
|
def local_storage
|
82
|
-
|
83
|
-
@@local_storage = Axiom::Adapter::Memory.new
|
84
|
-
end
|
85
|
-
@@local_storage
|
81
|
+
@@local_storage ||= Axiom::Adapter::Memory.new
|
86
82
|
end
|
87
83
|
|
88
84
|
def self.collection
|
89
85
|
@@local_storage[name_to_sym]
|
90
86
|
end
|
87
|
+
|
88
|
+
def self.all
|
89
|
+
self.collection.inject([]) do |list, relation|
|
90
|
+
list << self.cache_get(relation[:__cache_key])
|
91
|
+
end
|
92
|
+
end
|
91
93
|
|
92
|
-
#
|
93
|
-
#
|
94
|
+
# The where operation restricts the collection based on the
|
95
|
+
# passed in constraints.
|
96
|
+
#
|
97
|
+
# Pass in a key-value hash to restrict based on matching attributes by equality.
|
94
98
|
#
|
95
|
-
#
|
96
|
-
# a chainable scope object.
|
99
|
+
# Pass in a block to construct a more specialised predicate match.
|
97
100
|
#
|
98
101
|
def self.where(constraints)
|
99
102
|
self.collection.restrict(constraints).inject([]) do |list, relation|
|
100
|
-
list <<
|
103
|
+
list << self.cache_get(relation[:__cache_key])
|
101
104
|
end
|
102
105
|
end
|
106
|
+
|
107
|
+
# Order the collection by attribute and direction
|
108
|
+
# TODO: pass relations as scopes
|
109
|
+
def self.order(constraints)
|
110
|
+
ordered_relations = self.collection.sort_by do |relation|
|
111
|
+
constraints.keys.inject([]) do |list, constraint|
|
112
|
+
direction = constraints[constraint].to_sym
|
113
|
+
direction = :asc unless direction == :desc
|
114
|
+
list << relation.send(constraint.to_sym).send(direction)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
self.materialize(ordered_relations)
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def self.materialize(collection)
|
123
|
+
collection.inject([]) do |list, relation|
|
124
|
+
list << self.cache_get(relation[:__cache_key])
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.cache
|
129
|
+
@@cache ||= {}
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.cache_put(cache_key, object)
|
133
|
+
self.cache[cache_key] = object
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.cache_get(cache_key)
|
137
|
+
self.cache[cache_key]
|
138
|
+
end
|
103
139
|
|
104
140
|
end
|
105
141
|
end
|
data/lib/mementus/version.rb
CHANGED
data/mementus.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["me@maetl.net"]
|
11
11
|
spec.description = %q{In-memory data model}
|
12
12
|
spec.summary = %q{In-memory data model}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/maetl/mementus"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
data/spec/collection_spec.rb
CHANGED
@@ -22,11 +22,23 @@ describe Mementus::Model do
|
|
22
22
|
expect(Item.collection.count).to eq 20
|
23
23
|
end
|
24
24
|
|
25
|
-
it "
|
25
|
+
it "provides materialized objects" do
|
26
|
+
expect(Item.all.count).to eq 20
|
27
|
+
expect(Item.all.first.name).to eq "Item: 0"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "finds item by equality match" do
|
26
31
|
expect(Item.where(order: 10).count).to eq 1
|
27
32
|
expect(Item.where(order: 10).first.name).to eq "Item: 9"
|
28
33
|
end
|
29
34
|
|
35
|
+
it "finds items by predicate match" do
|
36
|
+
collection = Item.order(order: :desc)
|
37
|
+
expect(collection.count).to eq 20
|
38
|
+
expect(collection.first.name).to eq "Item: 19"
|
39
|
+
expect(collection.last.name).to eq "Item: 0"
|
40
|
+
end
|
41
|
+
|
30
42
|
end
|
31
43
|
|
32
44
|
end
|
data/spec/mapping_spec.rb
CHANGED
@@ -16,17 +16,17 @@ describe Mementus::Model do
|
|
16
16
|
)
|
17
17
|
}
|
18
18
|
|
19
|
-
let(:
|
20
|
-
|
19
|
+
let(:cache_key) {
|
20
|
+
mapping.cache_key
|
21
21
|
}
|
22
22
|
|
23
23
|
it "maps attribute schema to tuple" do
|
24
|
-
schema = [[:
|
24
|
+
schema = [[:__cache_key, String], [:description, String], [:number, Integer]]
|
25
25
|
expect(mapping.schema_tuple).to eq schema
|
26
26
|
end
|
27
27
|
|
28
28
|
it "maps attribute values to tuple" do
|
29
|
-
values = [
|
29
|
+
values = [mapping.cache_key, "Hello world.", 2014]
|
30
30
|
expect(mapping.values_tuple).to eq values
|
31
31
|
end
|
32
32
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mementus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- maetl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -101,7 +101,7 @@ files:
|
|
101
101
|
- spec/collection_spec.rb
|
102
102
|
- spec/mapping_spec.rb
|
103
103
|
- spec/spec_helper.rb
|
104
|
-
homepage:
|
104
|
+
homepage: https://github.com/maetl/mementus
|
105
105
|
licenses:
|
106
106
|
- MIT
|
107
107
|
metadata: {}
|