mementus 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- Mzg4MDg1OTYxZjllZGJiMWM1OGFjODc5MTcyNDQ1YzIyYmU3NzgwMA==
4
+ N2I2NmZkNjY1MGMwYWE0ZGI3ZmRmZjY0OGFlODI1YWQyZjhkMTU5OA==
5
5
  data.tar.gz: !binary |-
6
- YjcyZWZiNGE0ZTllMWU2MzI1Nzc1Yjg1ZDlkMGUzZGQxMTkyOWJhNg==
6
+ NDNhZGVhZjZlMWE5NzJmYmY5YjM0ODIxODA0ZDViZWZiNjZmNGExZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YjIyNDEyNTQyZWQwYzgzMzhlMzEzYTI5MzQyZDQ2YjE3MGQwYTZmMTljY2Vm
10
- MTIxZGVhMDJmYjQ2NWE3MTFjYWU0YjQxYWUyYTgyZTAxODEwM2UwNmIyNzM5
11
- YzI3MzI2ZmY4NjU5YmEyMTA4OTg3ZDBlNDM3MzFjZGY3MTVmZTg=
9
+ OWYyMGY5NDc1ODdkNGQ2ZmQ5ZDExZTI2ODA4MjUxZWYyM2RmYmM5NTE3ZTAx
10
+ NmQ4ODNjZTgxODQyZjdkZjFhYjMzNTQ4YTA2MDQ0YTU4NGY1MjVmMWI2NzZk
11
+ NTQ4ZjBiNGZmN2I0ODYxN2U2N2RjZDdmZWE3ZTM2YTNhZGJhMGQ=
12
12
  data.tar.gz: !binary |-
13
- NjZjOGRkZWZhMjE0MDVhM2NhZjk1NDg3NDE3N2JiYzBmMGVmMGY4NDQ5M2Zj
14
- N2Y0ZWQ5Y2QyNGRmZWY4YzdhOTJkOWIxNzA5OTYyY2JmOGZmZTJhNWM0ZGU0
15
- ZGI3N2NlYzYxYWQwZDUyMDY2NTU2ZjRkMmQwMmIxZTNkNTlhYzc=
13
+ NTlhZTVmODY1OGQ1MDhmYzU3MWE1NWM0NWUyMmM1MTIwMjY1YmNjZDkyMGJk
14
+ YzU4MTk2ODA5MGYyMWRlODk4YjZkOGFlZTkzMGNjZGQyNGI3MGI3M2I2NTI4
15
+ NzFkMGYzNDA1ODFkMTczMGMxOTA0MzdjYTU1MmEwMTI0OTIzMTU=
data/README.md CHANGED
@@ -2,20 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/maetl/mementus.svg?branch=master)](https://travis-ci.org/maetl/mementus)
4
4
 
5
- ```ruby
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
 
@@ -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 = [[:__object_id, String]]
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 = [object_id.to_s]
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
- unless @@local_storage
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
- # Stub implementation that demonstrates the ObjectSpace
93
- # reference grabbing.
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
- # Currently just splats to an array instead of handing back
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 << ObjectSpace._id2ref(relation[:__object_id].to_i)
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
@@ -1,3 +1,3 @@
1
1
  module Mementus
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
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($/)
@@ -22,11 +22,23 @@ describe Mementus::Model do
22
22
  expect(Item.collection.count).to eq 20
23
23
  end
24
24
 
25
- it "finds item by matching attribute" do
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(:object_id) {
20
- mapping.object_id.to_s
19
+ let(:cache_key) {
20
+ mapping.cache_key
21
21
  }
22
22
 
23
23
  it "maps attribute schema to tuple" do
24
- schema = [[:__object_id, String], [:description, String], [:number, Integer]]
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 = [object_id, "Hello world.", 2014]
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.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-06 00:00:00.000000000 Z
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: {}