factbase 0.0.45 → 0.0.47
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 +4 -4
- data/README.md +2 -2
- data/lib/factbase/fact.rb +4 -5
- data/lib/factbase/flatten.rb +44 -0
- data/lib/factbase/looged.rb +18 -13
- data/lib/factbase/to_json.rb +2 -2
- data/lib/factbase/to_xml.rb +2 -2
- data/lib/factbase/to_yaml.rb +2 -2
- data/lib/factbase.rb +6 -6
- data/test/factbase/test_fact.rb +12 -1
- data/test/factbase/test_flatten.rb +39 -0
- data/test/factbase/test_looged.rb +21 -2
- data/test/factbase/test_to_yaml.rb +3 -3
- data/test/test_factbase.rb +56 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b16ed7e90c154dfde3992d7a812c124caf6492c4f3600da01e93069e82be50f
|
4
|
+
data.tar.gz: 8cc18bca8d1a1eb3b52fdb314b38f87818796faf93d05395764d5968aa615a93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9376cb5f9cecf2fc5fb47296512285b8105b08fbe9683f3722995aac7bab5440a417d443f378dfc62c300f3b79d136f6365835843aabb3559eaf09f203404880
|
7
|
+
data.tar.gz: 59f4f461487d02b604b0614d571bbc10405a15c4d86ec92dedd8633d5b12a01bd92d546622aad23bd3d4caf65ff4a27ce7a18a6b1a65c6e2d54cbc0874f41d91
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Single-Table NoSQL In-Memory Database
|
1
|
+
# Single-Table NoSQL-ish In-Memory Database
|
2
2
|
|
3
3
|
[](http://www.rultor.com/p/yegor256/factbase)
|
4
4
|
[](https://www.jetbrains.com/ruby/)
|
@@ -18,7 +18,7 @@ It is possible to delete a fact, but impossible to delete a property
|
|
18
18
|
from a fact.
|
19
19
|
|
20
20
|
**ATTENTION**: The current implemention is naive and,
|
21
|
-
because of that, very slow
|
21
|
+
because of that, **very slow**. I will be very happy
|
22
22
|
if you suggest a better implementation without the change of the interface.
|
23
23
|
The `Factbase::query()` method is what mostly needs performance optimization:
|
24
24
|
currently it simply iterates through all facts in the factbase in order
|
data/lib/factbase/fact.rb
CHANGED
@@ -72,12 +72,11 @@ class Factbase::Fact
|
|
72
72
|
before = @map[kk]
|
73
73
|
return if before == v
|
74
74
|
if before.nil?
|
75
|
-
@map[kk] = v
|
76
|
-
|
75
|
+
@map[kk] = [v]
|
76
|
+
else
|
77
|
+
@map[kk] << v
|
78
|
+
@map[kk].uniq!
|
77
79
|
end
|
78
|
-
@map[kk] = [@map[kk]] unless @map[kk].is_a?(Array)
|
79
|
-
@map[kk] << v
|
80
|
-
@map[kk].uniq!
|
81
80
|
end
|
82
81
|
nil
|
83
82
|
elsif k == '[]'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require_relative '../factbase'
|
24
|
+
|
25
|
+
# Make maps suitable for printing.
|
26
|
+
#
|
27
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
28
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
29
|
+
# License:: MIT
|
30
|
+
class Factbase::Flatten
|
31
|
+
# Constructor.
|
32
|
+
def initialize(maps)
|
33
|
+
@maps = maps
|
34
|
+
end
|
35
|
+
|
36
|
+
# Improve the maps.
|
37
|
+
# @return [Array<HashMap>] The hashmaps, but improved
|
38
|
+
def it
|
39
|
+
@maps
|
40
|
+
.sort_by { |m| m[@sorter] }
|
41
|
+
.map { |m| m.sort.to_h }
|
42
|
+
.map { |m| m.transform_values { |v| v.size == 1 ? v[0] : v } }
|
43
|
+
end
|
44
|
+
end
|
data/lib/factbase/looged.rb
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'time'
|
24
24
|
require 'loog'
|
25
|
+
require_relative 'syntax'
|
25
26
|
|
26
27
|
# A decorator of a Factbase, that logs all operations.
|
27
28
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
@@ -48,17 +49,18 @@ class Factbase::Looged
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def query(query)
|
51
|
-
Query.new(@fb
|
52
|
+
Query.new(@fb, query, @loog)
|
52
53
|
end
|
53
54
|
|
54
55
|
def txn(this = self, &)
|
55
|
-
|
56
|
-
|
56
|
+
before = @fb.size
|
57
|
+
tail = nil
|
58
|
+
r = @fb.txn(this) do |fbt|
|
57
59
|
tail = Factbase::Looged.elapsed do
|
58
|
-
|
60
|
+
yield fbt
|
59
61
|
end
|
60
|
-
@loog.debug("Txn #{r ? 'modified' : 'did nothing'} #{tail}")
|
61
62
|
end
|
63
|
+
@loog.debug("Txn #{r ? 'modified' : 'didn\'t touch'} #{before} facts #{tail}")
|
62
64
|
r
|
63
65
|
end
|
64
66
|
|
@@ -113,8 +115,8 @@ class Factbase::Looged
|
|
113
115
|
# This is an internal class, it is not supposed to be instantiated directly.
|
114
116
|
#
|
115
117
|
class Query
|
116
|
-
def initialize(
|
117
|
-
@
|
118
|
+
def initialize(fb, expr, loog)
|
119
|
+
@fb = fb
|
118
120
|
@expr = expr
|
119
121
|
@loog = loog
|
120
122
|
end
|
@@ -124,7 +126,7 @@ class Factbase::Looged
|
|
124
126
|
if block_given?
|
125
127
|
r = nil
|
126
128
|
tail = Factbase::Looged.elapsed do
|
127
|
-
r = @query.each(&)
|
129
|
+
r = @fb.query(@expr).each(&)
|
128
130
|
end
|
129
131
|
raise ".each of #{@query.class} returned #{r.class}" unless r.is_a?(Integer)
|
130
132
|
if r.zero?
|
@@ -136,7 +138,7 @@ class Factbase::Looged
|
|
136
138
|
else
|
137
139
|
array = []
|
138
140
|
tail = Factbase::Looged.elapsed do
|
139
|
-
@query.each do |f|
|
141
|
+
@fb.query(@expr).each do |f|
|
140
142
|
array << f
|
141
143
|
end
|
142
144
|
end
|
@@ -151,14 +153,17 @@ class Factbase::Looged
|
|
151
153
|
|
152
154
|
def delete!
|
153
155
|
r = nil
|
156
|
+
before = @fb.size
|
154
157
|
tail = Factbase::Looged.elapsed do
|
155
|
-
r = @query.delete!
|
158
|
+
r = @fb.query(@expr).delete!
|
156
159
|
end
|
157
160
|
raise ".delete! of #{@query.class} returned #{r.class}" unless r.is_a?(Integer)
|
158
|
-
if
|
159
|
-
@loog.debug("
|
161
|
+
if before.zero?
|
162
|
+
@loog.debug("There were no facts, nothing deleted by '#{@expr}' #{tail}")
|
163
|
+
elsif r.zero?
|
164
|
+
@loog.debug("No facts out of #{before} deleted by '#{@expr}' #{tail}")
|
160
165
|
else
|
161
|
-
@loog.debug("Deleted #{r} fact(s) by '#{@expr}' #{tail}")
|
166
|
+
@loog.debug("Deleted #{r} fact(s) out of #{before} by '#{@expr}' #{tail}")
|
162
167
|
end
|
163
168
|
r
|
164
169
|
end
|
data/lib/factbase/to_json.rb
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'json'
|
24
24
|
require_relative '../factbase'
|
25
|
+
require_relative '../factbase/flatten'
|
25
26
|
|
26
27
|
# Factbase to JSON converter.
|
27
28
|
#
|
@@ -44,7 +45,6 @@ class Factbase::ToJSON
|
|
44
45
|
# Convert the entire factbase into JSON.
|
45
46
|
# @return [String] The factbase in JSON format
|
46
47
|
def json
|
47
|
-
|
48
|
-
maps.sort_by { |m| m[@sorter] }.map { |m| m.sort.to_h }.to_json
|
48
|
+
Factbase::Flatten.new(Marshal.load(@fb.export)).it.to_json
|
49
49
|
end
|
50
50
|
end
|
data/lib/factbase/to_xml.rb
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
require 'nokogiri'
|
24
24
|
require 'time'
|
25
25
|
require_relative '../factbase'
|
26
|
+
require_relative '../factbase/flatten'
|
26
27
|
|
27
28
|
# Factbase to XML converter.
|
28
29
|
#
|
@@ -46,14 +47,13 @@ class Factbase::ToXML
|
|
46
47
|
# @return [String] The factbase in XML format
|
47
48
|
def xml
|
48
49
|
bytes = @fb.export
|
49
|
-
maps = Marshal.load(bytes)
|
50
50
|
meta = {
|
51
51
|
version: Factbase::VERSION,
|
52
52
|
size: bytes.size
|
53
53
|
}
|
54
54
|
Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
55
55
|
xml.fb(meta) do
|
56
|
-
|
56
|
+
Factbase::Flatten.new(Marshal.load(bytes)).it.each do |m|
|
57
57
|
xml.f_ do
|
58
58
|
m.sort.to_h.each do |k, vv|
|
59
59
|
if vv.is_a?(Array)
|
data/lib/factbase/to_yaml.rb
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'yaml'
|
24
24
|
require_relative '../factbase'
|
25
|
+
require_relative '../factbase/flatten'
|
25
26
|
|
26
27
|
# Factbase to YAML converter.
|
27
28
|
#
|
@@ -44,7 +45,6 @@ class Factbase::ToYAML
|
|
44
45
|
# Convert the entire factbase into YAML.
|
45
46
|
# @return [String] The factbase in YAML format
|
46
47
|
def yaml
|
47
|
-
|
48
|
-
YAML.dump({ 'facts' => maps.sort_by { |m| m[@sorter] }.map { |m| m.sort.to_h } })
|
48
|
+
YAML.dump(Factbase::Flatten.new(Marshal.load(@fb.export)).it)
|
49
49
|
end
|
50
50
|
end
|
data/lib/factbase.rb
CHANGED
@@ -79,7 +79,7 @@ require 'yaml'
|
|
79
79
|
# License:: MIT
|
80
80
|
class Factbase
|
81
81
|
# Current version of the gem (changed by .rultor.yml on every release)
|
82
|
-
VERSION = '0.0.
|
82
|
+
VERSION = '0.0.47'
|
83
83
|
|
84
84
|
# An exception that may be thrown in a transaction, to roll it back.
|
85
85
|
class Rollback < StandardError; end
|
@@ -91,10 +91,10 @@ class Factbase
|
|
91
91
|
@mutex = Mutex.new
|
92
92
|
end
|
93
93
|
|
94
|
-
# Make a duplicate of this factbase.
|
94
|
+
# Make a deep duplicate of this factbase.
|
95
95
|
# @return [Factbase] A new factbase
|
96
96
|
def dup
|
97
|
-
Factbase.new(@maps.dup)
|
97
|
+
Factbase.new(@maps.map { |m| m.transform_values(&:dup) })
|
98
98
|
end
|
99
99
|
|
100
100
|
# Size.
|
@@ -175,9 +175,9 @@ class Factbase
|
|
175
175
|
@maps << {}
|
176
176
|
modified = true
|
177
177
|
end
|
178
|
-
m.each do |k,
|
179
|
-
next if @maps[i][k] ==
|
180
|
-
@maps[i][k] =
|
178
|
+
m.each do |k, vv|
|
179
|
+
next if @maps[i][k] == vv
|
180
|
+
@maps[i][k] = vv
|
181
181
|
modified = true
|
182
182
|
end
|
183
183
|
end
|
data/test/factbase/test_fact.rb
CHANGED
@@ -29,6 +29,17 @@ require_relative '../../lib/factbase/fact'
|
|
29
29
|
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
30
30
|
# License:: MIT
|
31
31
|
class TestFact < Minitest::Test
|
32
|
+
def test_injects_data_correctly
|
33
|
+
map = {}
|
34
|
+
f = Factbase::Fact.new(Mutex.new, map)
|
35
|
+
f.foo = 1
|
36
|
+
f.bar = 2
|
37
|
+
f.bar = 3
|
38
|
+
assert_equal(2, map.size)
|
39
|
+
assert_equal([1], map['foo'])
|
40
|
+
assert_equal([2, 3], map['bar'])
|
41
|
+
end
|
42
|
+
|
32
43
|
def test_simple_resetting
|
33
44
|
map = {}
|
34
45
|
f = Factbase::Fact.new(Mutex.new, map)
|
@@ -89,7 +100,7 @@ class TestFact < Minitest::Test
|
|
89
100
|
f = Factbase::Fact.new(Mutex.new, map)
|
90
101
|
f.foo = 42
|
91
102
|
f.foo = 42
|
92
|
-
assert_equal(42, map['foo'])
|
103
|
+
assert_equal([42], map['foo'])
|
93
104
|
end
|
94
105
|
|
95
106
|
def test_time_in_utc
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require_relative '../../lib/factbase'
|
25
|
+
require_relative '../../lib/factbase/flatten'
|
26
|
+
|
27
|
+
# Test.
|
28
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
30
|
+
# License:: MIT
|
31
|
+
class TestFlatten < Minitest::Test
|
32
|
+
def test_mapping
|
33
|
+
maps = [{ 'b' => [42] }, { 'a' => 33 }, { 'c' => %w[hey you] }]
|
34
|
+
to = Factbase::Flatten.new(maps).it
|
35
|
+
assert(33, to[0]['a'])
|
36
|
+
assert(42, to[1]['b'])
|
37
|
+
assert(2, to[2]['c'].size)
|
38
|
+
end
|
39
|
+
end
|
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'minitest/autorun'
|
24
24
|
require 'loog'
|
25
|
+
require_relative '../../lib/factbase'
|
25
26
|
require_relative '../../lib/factbase/looged'
|
26
27
|
|
27
28
|
# Test.
|
@@ -45,13 +46,31 @@ class TestLooged < Minitest::Test
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def test_with_txn
|
48
|
-
|
49
|
+
log = Loog::Buffer.new
|
50
|
+
fb = Factbase::Looged.new(Factbase.new, log)
|
49
51
|
assert(
|
50
52
|
fb.txn do |fbt|
|
51
53
|
fbt.insert.foo = 42
|
52
54
|
end
|
53
55
|
)
|
54
56
|
assert_equal(1, fb.size)
|
57
|
+
assert(log.to_s.include?('modified'), log)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_with_modifying_txn
|
61
|
+
log = Loog::Buffer.new
|
62
|
+
fb = Factbase::Looged.new(Factbase.new, log)
|
63
|
+
fb.insert.foo = 1
|
64
|
+
assert(!fb.txn { |fbt| fbt.query('(always)').each.to_a }, log)
|
65
|
+
assert(fb.txn { |fbt| fbt.query('(always)').each.to_a[0].foo = 42 }, log)
|
66
|
+
assert(log.to_s.include?('modified'), log)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_with_empty_txn
|
70
|
+
log = Loog::Buffer.new
|
71
|
+
fb = Factbase::Looged.new(Factbase.new, log)
|
72
|
+
assert(!fb.txn { |fbt| fbt.query('(always)').each.to_a })
|
73
|
+
assert(log.to_s.include?('didn\'t touch'), log)
|
55
74
|
end
|
56
75
|
|
57
76
|
def test_returns_int
|
@@ -102,7 +121,7 @@ class TestLooged < Minitest::Test
|
|
102
121
|
'Set \'bar\' to 3 (Integer)',
|
103
122
|
'Set \'str\' to "Он поскорей звонит. Вбегает\n ... Отъехать в поле к двум дубкам." (String)',
|
104
123
|
'Found 1 fact(s) by \'(exists bar)\'',
|
105
|
-
'Deleted 3 fact(s) by \'(not (exists bar))\''
|
124
|
+
'Deleted 3 fact(s) out of 4 by \'(not (exists bar))\''
|
106
125
|
].each do |s|
|
107
126
|
assert(log.to_s.include?(s), "#{log}\n")
|
108
127
|
end
|
@@ -39,9 +39,9 @@ class TestToYAML < Minitest::Test
|
|
39
39
|
fb.insert._id = 2
|
40
40
|
to = Factbase::ToYAML.new(fb)
|
41
41
|
yaml = YAML.load(to.yaml)
|
42
|
-
assert_equal(2, yaml
|
43
|
-
assert_equal(42, yaml[
|
44
|
-
assert_equal(256, yaml[
|
42
|
+
assert_equal(2, yaml.size)
|
43
|
+
assert_equal(42, yaml[0]['foo'][0])
|
44
|
+
assert_equal(256, yaml[0]['foo'][1])
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_sorts_keys
|
data/test/test_factbase.rb
CHANGED
@@ -23,12 +23,31 @@
|
|
23
23
|
require 'minitest/autorun'
|
24
24
|
require 'loog'
|
25
25
|
require_relative '../lib/factbase'
|
26
|
+
require_relative '../lib/factbase/rules'
|
27
|
+
require_relative '../lib/factbase/inv'
|
28
|
+
require_relative '../lib/factbase/pre'
|
29
|
+
require_relative '../lib/factbase/looged'
|
26
30
|
|
27
31
|
# Factbase main module test.
|
28
32
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
33
|
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
30
34
|
# License:: MIT
|
31
35
|
class TestFactbase < Minitest::Test
|
36
|
+
def test_injects_data_correctly
|
37
|
+
maps = []
|
38
|
+
fb = Factbase.new(maps)
|
39
|
+
fb.insert
|
40
|
+
f = fb.insert
|
41
|
+
f.foo = 1
|
42
|
+
f.bar = 2
|
43
|
+
f.bar = 3
|
44
|
+
assert_equal(2, maps.size)
|
45
|
+
assert_equal(0, maps[0].size)
|
46
|
+
assert_equal(2, maps[1].size)
|
47
|
+
assert_equal([1], maps[1]['foo'])
|
48
|
+
assert_equal([2, 3], maps[1]['bar'])
|
49
|
+
end
|
50
|
+
|
32
51
|
def test_simple_setting
|
33
52
|
fb = Factbase.new
|
34
53
|
fb.insert
|
@@ -44,6 +63,22 @@ class TestFactbase < Minitest::Test
|
|
44
63
|
assert_equal(2, fb.size)
|
45
64
|
end
|
46
65
|
|
66
|
+
def test_modify_via_query
|
67
|
+
fb = Factbase.new
|
68
|
+
fb.insert.bar = 1
|
69
|
+
fb.query('(exists bar)').each do |f|
|
70
|
+
f.bar = 42
|
71
|
+
assert_equal([1, 42], f['bar'])
|
72
|
+
end
|
73
|
+
found = 0
|
74
|
+
fb.query('(always)').each do |f|
|
75
|
+
assert_equal([1, 42], f['bar'])
|
76
|
+
found += 1
|
77
|
+
end
|
78
|
+
assert_equal(1, found)
|
79
|
+
assert_equal([1, 42], fb.query('(always)').each.to_a[0]['bar'])
|
80
|
+
end
|
81
|
+
|
47
82
|
def test_serialize_and_deserialize
|
48
83
|
f1 = Factbase.new
|
49
84
|
f2 = Factbase.new
|
@@ -72,6 +107,16 @@ class TestFactbase < Minitest::Test
|
|
72
107
|
assert_equal(2, fb2.size)
|
73
108
|
end
|
74
109
|
|
110
|
+
def test_txn_returns_boolean
|
111
|
+
fb = Factbase.new
|
112
|
+
assert(fb.txn { true }.is_a?(FalseClass))
|
113
|
+
assert(fb.txn(&:insert).is_a?(TrueClass))
|
114
|
+
assert(fb.txn { |fbt| fbt.insert.bar = 42 })
|
115
|
+
assert(!fb.txn { |fbt| fbt.query('(always)').each.to_a })
|
116
|
+
assert(fb.txn { |fbt| fbt.query('(always)').each { |f| f.hello = 33 } })
|
117
|
+
assert(fb.txn { |fbt| fbt.query('(always)').each.to_a[0].zzz = 33 })
|
118
|
+
end
|
119
|
+
|
75
120
|
def test_run_txn
|
76
121
|
fb = Factbase.new
|
77
122
|
fb.txn do |fbt|
|
@@ -90,6 +135,17 @@ class TestFactbase < Minitest::Test
|
|
90
135
|
assert_equal(2, fb.size)
|
91
136
|
end
|
92
137
|
|
138
|
+
def test_run_txn_via_query
|
139
|
+
fb = Factbase.new
|
140
|
+
fb.insert.foo = 1
|
141
|
+
assert(
|
142
|
+
fb.txn do |fbt|
|
143
|
+
fbt.query('(always)').each { |f| f.foo = 42 }
|
144
|
+
end
|
145
|
+
)
|
146
|
+
assert_equal([1, 42], fb.query('(always)').each.to_a[0]['foo'])
|
147
|
+
end
|
148
|
+
|
93
149
|
def test_run_txn_with_inv
|
94
150
|
fb = Factbase::Inv.new(Factbase.new) { |_p, v| throw 'oops' if v == 42 }
|
95
151
|
fb.insert.bar = 3
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.47
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- factbase.gemspec
|
103
103
|
- lib/factbase.rb
|
104
104
|
- lib/factbase/fact.rb
|
105
|
+
- lib/factbase/flatten.rb
|
105
106
|
- lib/factbase/inv.rb
|
106
107
|
- lib/factbase/looged.rb
|
107
108
|
- lib/factbase/pre.rb
|
@@ -115,6 +116,7 @@ files:
|
|
115
116
|
- lib/factbase/tuples.rb
|
116
117
|
- renovate.json
|
117
118
|
- test/factbase/test_fact.rb
|
119
|
+
- test/factbase/test_flatten.rb
|
118
120
|
- test/factbase/test_inv.rb
|
119
121
|
- test/factbase/test_looged.rb
|
120
122
|
- test/factbase/test_pre.rb
|