factbase 0.0.51 → 0.0.52
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/Gemfile +3 -3
- data/Gemfile.lock +6 -6
- data/README.md +7 -2
- data/lib/factbase/accum.rb +2 -1
- data/lib/factbase/looged.rb +17 -3
- data/lib/factbase/query.rb +20 -3
- data/lib/factbase/rules.rb +6 -2
- data/lib/factbase/tee.rb +4 -2
- data/lib/factbase/terms/aggregates.rb +8 -1
- data/lib/factbase/terms/aliases.rb +11 -7
- data/lib/factbase.rb +1 -1
- data/test/factbase/terms/test_aggregates.rb +20 -6
- data/test/factbase/terms/test_aliases.rb +8 -5
- data/test/factbase/test_looged.rb +8 -0
- data/test/factbase/test_query.rb +28 -0
- data/test/factbase/test_rules.rb +8 -1
- data/test/factbase/test_tee.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a70fcc45481bd1611d6bf2ed5c41ef40fe6f1ce67494abfa769c3b859b215960
|
4
|
+
data.tar.gz: 609bd76eaca6f4668bbbf5678514503edb1f9184e9abd62321dc02cdd614f80c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97e8cc3c9f53349aaf85aa3f95ba9f0e2525dd85f242ade079083b4ffab042dbb0b3f1ad776573646f7fae0107e709404b70e340fc9660b99ef8770a313aa8a9
|
7
|
+
data.tar.gz: e4d9404781d0314d4e6aa22f93affc3260fc053121c9e70204f8690d30de34feb26533254f15519b9e2562a5562e93398779d890ab78c3acc3afcd8ed8fba782
|
data/Gemfile
CHANGED
@@ -23,11 +23,11 @@
|
|
23
23
|
source 'https://rubygems.org'
|
24
24
|
gemspec
|
25
25
|
|
26
|
-
gem 'minitest', '5.
|
26
|
+
gem 'minitest', '5.24.0', require: false
|
27
27
|
gem 'rake', '13.2.1', require: false
|
28
|
-
gem 'rspec-rails', '6.1.
|
28
|
+
gem 'rspec-rails', '6.1.3', require: false
|
29
29
|
gem 'rubocop', '1.64.1', require: false
|
30
|
-
gem 'rubocop-performance', '1.21.
|
30
|
+
gem 'rubocop-performance', '1.21.1', require: false
|
31
31
|
gem 'rubocop-rspec', '3.0.1', require: false
|
32
32
|
gem 'simplecov', '0.22.0', require: false
|
33
33
|
gem 'simplecov-cobertura', '2.1.0', require: false
|
data/Gemfile.lock
CHANGED
@@ -62,7 +62,7 @@ GEM
|
|
62
62
|
crass (~> 1.0.2)
|
63
63
|
nokogiri (>= 1.12.0)
|
64
64
|
loog (0.5.1)
|
65
|
-
minitest (5.
|
65
|
+
minitest (5.24.0)
|
66
66
|
mutex_m (0.2.0)
|
67
67
|
nokogiri (1.16.6-arm64-darwin)
|
68
68
|
racc (~> 1.4)
|
@@ -119,7 +119,7 @@ GEM
|
|
119
119
|
rspec-mocks (3.13.1)
|
120
120
|
diff-lcs (>= 1.2.0, < 2.0)
|
121
121
|
rspec-support (~> 3.13.0)
|
122
|
-
rspec-rails (6.1.
|
122
|
+
rspec-rails (6.1.3)
|
123
123
|
actionpack (>= 6.1)
|
124
124
|
activesupport (>= 6.1)
|
125
125
|
railties (>= 6.1)
|
@@ -141,7 +141,7 @@ GEM
|
|
141
141
|
unicode-display_width (>= 2.4.0, < 3.0)
|
142
142
|
rubocop-ast (1.31.3)
|
143
143
|
parser (>= 3.3.1.0)
|
144
|
-
rubocop-performance (1.21.
|
144
|
+
rubocop-performance (1.21.1)
|
145
145
|
rubocop (>= 1.48.1, < 2.0)
|
146
146
|
rubocop-ast (>= 1.31.1, < 2.0)
|
147
147
|
rubocop-rspec (3.0.1)
|
@@ -176,11 +176,11 @@ PLATFORMS
|
|
176
176
|
|
177
177
|
DEPENDENCIES
|
178
178
|
factbase!
|
179
|
-
minitest (= 5.
|
179
|
+
minitest (= 5.24.0)
|
180
180
|
rake (= 13.2.1)
|
181
|
-
rspec-rails (= 6.1.
|
181
|
+
rspec-rails (= 6.1.3)
|
182
182
|
rubocop (= 1.64.1)
|
183
|
-
rubocop-performance (= 1.21.
|
183
|
+
rubocop-performance (= 1.21.1)
|
184
184
|
rubocop-rspec (= 3.0.1)
|
185
185
|
simplecov (= 0.22.0)
|
186
186
|
simplecov-cobertura (= 2.1.0)
|
data/README.md
CHANGED
@@ -86,8 +86,9 @@ It's possible to modify the facts retrieved, on fly:
|
|
86
86
|
|
87
87
|
* `(as p v)` adds property `p` with the value `v`
|
88
88
|
* `(join s t)` adds properties named by the `s` mask with the values retrieved
|
89
|
-
by the `t` term, for example, `(join "
|
90
|
-
|
89
|
+
by the `t` term, for example, `(join "x<=foo,y<=bar" (gt x 5))` will add
|
90
|
+
`x` and `y` properties, setting them to values found in the `foo` and `bar`
|
91
|
+
properties in the facts that match `(gt x 5)`
|
91
92
|
|
92
93
|
Also, some simple arithmetic:
|
93
94
|
|
@@ -128,6 +129,10 @@ a positive integer)
|
|
128
129
|
* `(min p)` returns the minimum
|
129
130
|
* `(sum p)` returns the arithmetic sum of all values of the `p` property
|
130
131
|
|
132
|
+
It's also possible to use a sub-query in a shorter form than with the `agg`:
|
133
|
+
|
134
|
+
* `(empty q)` is true if the subquery `q` is empty
|
135
|
+
|
131
136
|
## How to contribute
|
132
137
|
|
133
138
|
Read
|
data/lib/factbase/accum.rb
CHANGED
@@ -39,7 +39,7 @@ class Factbase::Accum
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def to_s
|
42
|
-
@fact
|
42
|
+
"#{@fact} + #{@props}"
|
43
43
|
end
|
44
44
|
|
45
45
|
def method_missing(*args)
|
@@ -55,6 +55,7 @@ class Factbase::Accum
|
|
55
55
|
kk = args[1].to_s
|
56
56
|
vv = @props[kk].nil? ? [] : @props[kk]
|
57
57
|
vvv = @fact.method_missing(*args)
|
58
|
+
vvv = [vvv] unless vvv.nil? || vvv.is_a?(Array)
|
58
59
|
vv += vvv unless vvv.nil?
|
59
60
|
vv.uniq!
|
60
61
|
return vv.empty? ? nil : vv
|
data/lib/factbase/looged.rb
CHANGED
@@ -129,12 +129,26 @@ class Factbase::Looged
|
|
129
129
|
@loog = loog
|
130
130
|
end
|
131
131
|
|
132
|
-
def
|
132
|
+
def one(params = {})
|
133
|
+
q = Factbase::Syntax.new(@expr).to_term.to_s
|
134
|
+
r = nil
|
135
|
+
tail = Factbase::Looged.elapsed do
|
136
|
+
r = @fb.query(@expr).one(params)
|
137
|
+
end
|
138
|
+
if r.nil?
|
139
|
+
@loog.debug("Nothing found by '#{q}' #{tail}")
|
140
|
+
else
|
141
|
+
@loog.debug("Found #{r} (#{r.class}) by '#{q}' #{tail}")
|
142
|
+
end
|
143
|
+
r
|
144
|
+
end
|
145
|
+
|
146
|
+
def each(params = {}, &)
|
133
147
|
q = Factbase::Syntax.new(@expr).to_term.to_s
|
134
148
|
if block_given?
|
135
149
|
r = nil
|
136
150
|
tail = Factbase::Looged.elapsed do
|
137
|
-
r = @fb.query(@expr).each(&)
|
151
|
+
r = @fb.query(@expr).each(params, &)
|
138
152
|
end
|
139
153
|
raise ".each of #{@query.class} returned #{r.class}" unless r.is_a?(Integer)
|
140
154
|
if r.zero?
|
@@ -146,7 +160,7 @@ class Factbase::Looged
|
|
146
160
|
else
|
147
161
|
array = []
|
148
162
|
tail = Factbase::Looged.elapsed do
|
149
|
-
@fb.query(@expr).each do |f|
|
163
|
+
@fb.query(@expr).each(params) do |f|
|
150
164
|
array << f
|
151
165
|
end
|
152
166
|
end
|
data/lib/factbase/query.rb
CHANGED
@@ -24,6 +24,7 @@ require_relative '../factbase'
|
|
24
24
|
require_relative 'syntax'
|
25
25
|
require_relative 'fact'
|
26
26
|
require_relative 'accum'
|
27
|
+
require_relative 'tee'
|
27
28
|
|
28
29
|
# Query.
|
29
30
|
#
|
@@ -46,16 +47,19 @@ class Factbase::Query
|
|
46
47
|
@query = query
|
47
48
|
end
|
48
49
|
|
49
|
-
# Iterate
|
50
|
+
# Iterate facts one by one.
|
51
|
+
# @param [Hash] params Optional params accessible in the query via the "$" symbol
|
50
52
|
# @yield [Fact] Facts one-by-one
|
51
53
|
# @return [Integer] Total number of facts yielded
|
52
|
-
def each
|
53
|
-
return to_enum(__method__) unless block_given?
|
54
|
+
def each(params = {})
|
55
|
+
return to_enum(__method__, params) unless block_given?
|
54
56
|
term = Factbase::Syntax.new(@query).to_term
|
55
57
|
yielded = 0
|
56
58
|
@maps.each do |m|
|
57
59
|
extras = {}
|
58
60
|
f = Factbase::Fact.new(@mutex, m)
|
61
|
+
params = params.transform_keys(&:to_s) if params.is_a?(Hash)
|
62
|
+
f = Factbase::Tee.new(f, params)
|
59
63
|
a = Factbase::Accum.new(f, extras, false)
|
60
64
|
r = term.evaluate(a, @maps)
|
61
65
|
unless r.is_a?(TrueClass) || r.is_a?(FalseClass)
|
@@ -68,6 +72,19 @@ class Factbase::Query
|
|
68
72
|
yielded
|
69
73
|
end
|
70
74
|
|
75
|
+
# Read a single value.
|
76
|
+
# @param [Hash] params Optional params accessible in the query via the "$" symbol
|
77
|
+
# @return The value evaluated
|
78
|
+
def one(params = {})
|
79
|
+
term = Factbase::Syntax.new(@query).to_term
|
80
|
+
params = params.transform_keys(&:to_s) if params.is_a?(Hash)
|
81
|
+
r = term.evaluate(Factbase::Tee.new(nil, params), @maps)
|
82
|
+
unless %w[String Integer Float Time Array NilClass].include?(r.class.to_s)
|
83
|
+
raise "Incorrect type #{r.class} returned by #{@query}"
|
84
|
+
end
|
85
|
+
r
|
86
|
+
end
|
87
|
+
|
71
88
|
# Delete all facts that match the query.
|
72
89
|
# @return [Integer] Total number of facts deleted
|
73
90
|
def delete!
|
data/lib/factbase/rules.rb
CHANGED
@@ -126,8 +126,12 @@ class Factbase::Rules
|
|
126
126
|
@check = check
|
127
127
|
end
|
128
128
|
|
129
|
-
def
|
130
|
-
|
129
|
+
def one(params = {})
|
130
|
+
@query.one(params)
|
131
|
+
end
|
132
|
+
|
133
|
+
def each(params = {})
|
134
|
+
return to_enum(__method__, params) unless block_given?
|
131
135
|
@query.each do |f|
|
132
136
|
yield Fact.new(f, @check)
|
133
137
|
end
|
data/lib/factbase/tee.rb
CHANGED
@@ -41,8 +41,10 @@ class Factbase::Tee
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def method_missing(*args)
|
44
|
-
return @
|
45
|
-
|
44
|
+
return @fact.method_missing(*args) unless args[0].to_s == '[]' && args[1].to_s.start_with?('$')
|
45
|
+
n = args[1].to_s
|
46
|
+
n = n[1..] unless @upper.is_a?(Factbase::Tee)
|
47
|
+
@upper[n]
|
46
48
|
end
|
47
49
|
|
48
50
|
# rubocop:disable Style/OptionalBooleanParameter
|
@@ -81,10 +81,17 @@ module Factbase::Term::Aggregates
|
|
81
81
|
raise "A term expected, but '#{selector}' provided" unless selector.is_a?(Factbase::Term)
|
82
82
|
term = @operands[1]
|
83
83
|
raise "A term expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
84
|
-
subset =
|
84
|
+
subset = Factbase::Query.new(maps, Mutex.new, selector.to_s).each(fact).to_a
|
85
85
|
term.evaluate(nil, subset)
|
86
86
|
end
|
87
87
|
|
88
|
+
def empty(fact, maps)
|
89
|
+
assert_args(1)
|
90
|
+
term = @operands[0]
|
91
|
+
raise "A term expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
92
|
+
Factbase::Query.new(maps, Mutex.new, term.to_s).each(fact).to_a.empty?
|
93
|
+
end
|
94
|
+
|
88
95
|
def best(maps)
|
89
96
|
k = @operands[0]
|
90
97
|
raise "A symbol expected, but #{k} provided" unless k.is_a?(Symbol)
|
@@ -39,15 +39,19 @@ module Factbase::Term::Aliases
|
|
39
39
|
|
40
40
|
def join(fact, maps)
|
41
41
|
assert_args(2)
|
42
|
-
|
43
|
-
raise "A string expected as first argument of 'join'" unless
|
42
|
+
jumps = @operands[0]
|
43
|
+
raise "A string expected as first argument of 'join'" unless jumps.is_a?(String)
|
44
|
+
jumps = jumps.split(',')
|
45
|
+
.map(&:strip)
|
46
|
+
.map { |j| j.split('<=').map(&:strip) }
|
47
|
+
.map { |j| j.size == 1 ? [j[0], j[0]] : j }
|
44
48
|
term = @operands[1]
|
45
49
|
raise "A term expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
46
|
-
subset =
|
47
|
-
subset.each do |
|
48
|
-
|
49
|
-
|
50
|
-
fact.send("#{
|
50
|
+
subset = Factbase::Query.new(maps, Mutex.new, term.to_s).each(fact).to_a
|
51
|
+
subset.each do |s|
|
52
|
+
jumps.each do |to, from|
|
53
|
+
s[from]&.each do |v|
|
54
|
+
fact.send("#{to}=", v)
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
data/lib/factbase.rb
CHANGED
@@ -81,7 +81,7 @@ require 'yaml'
|
|
81
81
|
# License:: MIT
|
82
82
|
class Factbase
|
83
83
|
# Current version of the gem (changed by .rultor.yml on every release)
|
84
|
-
VERSION = '0.0.
|
84
|
+
VERSION = '0.0.52'
|
85
85
|
|
86
86
|
# An exception that may be thrown in a transaction, to roll it back.
|
87
87
|
class Rollback < StandardError; end
|
@@ -31,12 +31,12 @@ require_relative '../../../lib/factbase/syntax'
|
|
31
31
|
class TestAggregates < Minitest::Test
|
32
32
|
def test_aggregation
|
33
33
|
maps = [
|
34
|
-
{ 'x' => 1, 'y' => 0, 'z' => 4 },
|
35
|
-
{ 'x' => 2, 'y' => 42, 'z' => 3 },
|
36
|
-
{ 'x' => 3, 'y' => 42, 'z' => 5 },
|
37
|
-
{ 'x' => 4, 'y' => 42, 'z' => 2 },
|
38
|
-
{ 'x' => 5, 'y' => 42, 'z' => 1 },
|
39
|
-
{ 'x' => 8, 'y' => 0, 'z' => 6 }
|
34
|
+
{ 'x' => [1], 'y' => [0], 'z' => [4] },
|
35
|
+
{ 'x' => [2], 'y' => [42], 'z' => [3] },
|
36
|
+
{ 'x' => [3], 'y' => [42], 'z' => [5] },
|
37
|
+
{ 'x' => [4], 'y' => [42], 'z' => [2] },
|
38
|
+
{ 'x' => [5], 'y' => [42], 'z' => [1] },
|
39
|
+
{ 'x' => [8], 'y' => [0], 'z' => [6] }
|
40
40
|
]
|
41
41
|
{
|
42
42
|
'(eq x (agg (eq y 42) (min x)))' => '(eq x 2)',
|
@@ -54,6 +54,20 @@ class TestAggregates < Minitest::Test
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
def test_empty
|
58
|
+
maps = [
|
59
|
+
{ 'x' => [1], 'y' => [0], 'z' => [4] },
|
60
|
+
{ 'x' => [8], 'y' => [0] }
|
61
|
+
]
|
62
|
+
{
|
63
|
+
'(empty (eq y 42))' => true,
|
64
|
+
'(empty (eq x 1))' => false
|
65
|
+
}.each do |q, r|
|
66
|
+
t = Factbase::Syntax.new(q).to_term
|
67
|
+
assert_equal(r, t.evaluate(nil, maps), q)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
57
71
|
private
|
58
72
|
|
59
73
|
def fact(map = {})
|
@@ -51,19 +51,22 @@ class TestAliases < Minitest::Test
|
|
51
51
|
|
52
52
|
def test_join
|
53
53
|
maps = [
|
54
|
-
{ 'x' =>
|
54
|
+
{ 'x' => 1, 'y' => 0, 'z' => 4 },
|
55
55
|
{ 'x' => [2], 'bar' => [44, 55, 66] }
|
56
56
|
]
|
57
57
|
{
|
58
|
-
'(join "
|
59
|
-
'(join "
|
60
|
-
'(join "
|
58
|
+
'(join "foo_x<=x" (gt x 1))' => '(exists foo_x)',
|
59
|
+
'(join "foo <=bar " (exists bar))' => '(and (eq foo 44) (eq foo 55))',
|
60
|
+
'(join "uuu" (eq x 1))' => '(absent uuu)',
|
61
|
+
'(join "uuu <= fff" (eq fff 1))' => '(absent uuu)'
|
61
62
|
}.each do |q, r|
|
62
63
|
t = Factbase::Syntax.new(q).to_term
|
63
64
|
maps.each do |m|
|
64
65
|
f = Factbase::Accum.new(fact(m), {}, false)
|
66
|
+
require_relative '../../../lib/factbase/looged'
|
67
|
+
f = Factbase::Looged::Fact.new(f, Loog::NULL)
|
65
68
|
next unless t.evaluate(f, maps)
|
66
|
-
assert(Factbase::Syntax.new(r).to_term.evaluate(f, []), "#{q} -> #{f}")
|
69
|
+
assert(Factbase::Syntax.new(r).to_term.evaluate(f, []), "#{q} -> #{f} doesn't match #{r}")
|
67
70
|
end
|
68
71
|
end
|
69
72
|
end
|
@@ -45,6 +45,14 @@ class TestLooged < Minitest::Test
|
|
45
45
|
assert_equal(2, fb.size)
|
46
46
|
end
|
47
47
|
|
48
|
+
def test_reading_one
|
49
|
+
fb = Factbase::Looged.new(Factbase.new, Loog::NULL)
|
50
|
+
fb.insert
|
51
|
+
fb.insert.bar = 42
|
52
|
+
assert_equal(1, fb.query('(agg (exists bar) (count))').one)
|
53
|
+
assert_equal([42], fb.query('(agg (exists bar) (first bar))').one)
|
54
|
+
end
|
55
|
+
|
48
56
|
def test_with_txn
|
49
57
|
log = Loog::Buffer.new
|
50
58
|
fb = Factbase::Looged.new(Factbase.new, log)
|
data/test/factbase/test_query.rb
CHANGED
@@ -110,6 +110,21 @@ class TestQuery < Minitest::Test
|
|
110
110
|
assert_equal(1, maps.size)
|
111
111
|
end
|
112
112
|
|
113
|
+
def test_reading_one
|
114
|
+
maps = []
|
115
|
+
maps << { 'foo' => [42] }
|
116
|
+
maps << { 'bar' => [4, 5] }
|
117
|
+
{
|
118
|
+
'(agg (exists foo) (first foo))' => [42],
|
119
|
+
'(agg (exists z) (first z))' => nil,
|
120
|
+
'(agg (always) (count))' => 2,
|
121
|
+
'(agg (eq bar $v) (count))' => 1,
|
122
|
+
'(agg (eq z 40) (count))' => 0
|
123
|
+
}.each do |q, r|
|
124
|
+
assert_equal(r, Factbase::Query.new(maps, Mutex.new, q).one(v: 4), "#{q} -> #{r}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
113
128
|
def test_deleting_nothing
|
114
129
|
maps = []
|
115
130
|
maps << { 'foo' => [42] }
|
@@ -140,6 +155,19 @@ class TestQuery < Minitest::Test
|
|
140
155
|
assert_equal(1, maps[0].size)
|
141
156
|
end
|
142
157
|
|
158
|
+
def test_with_params
|
159
|
+
maps = []
|
160
|
+
maps << { 'foo' => [42] }
|
161
|
+
maps << { 'foo' => [17] }
|
162
|
+
found = 0
|
163
|
+
Factbase::Query.new(maps, Mutex.new, '(eq foo $bar)').each(bar: [42]) do
|
164
|
+
found += 1
|
165
|
+
end
|
166
|
+
assert_equal(1, found)
|
167
|
+
assert_equal(1, Factbase::Query.new(maps, Mutex.new, '(eq foo $bar)').each(bar: 42).to_a.size)
|
168
|
+
assert_equal(0, Factbase::Query.new(maps, Mutex.new, '(eq foo $bar)').each(bar: 555).to_a.size)
|
169
|
+
end
|
170
|
+
|
143
171
|
def test_with_nil_alias
|
144
172
|
maps = []
|
145
173
|
maps << { 'foo' => [42] }
|
data/test/factbase/test_rules.rb
CHANGED
@@ -53,6 +53,13 @@ class TestRules < Minitest::Test
|
|
53
53
|
assert(f.to_s.length.positive?)
|
54
54
|
end
|
55
55
|
|
56
|
+
def test_query_one
|
57
|
+
fb = Factbase::Rules.new(Factbase.new, '(always)')
|
58
|
+
f = fb.insert
|
59
|
+
f.foo = 42
|
60
|
+
assert_equal(1, fb.query('(agg (eq foo $v) (count))').one(v: 42))
|
61
|
+
end
|
62
|
+
|
56
63
|
def test_check_only_when_txn_is_closed
|
57
64
|
fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
|
58
65
|
ok = false
|
@@ -94,6 +101,6 @@ class TestRules < Minitest::Test
|
|
94
101
|
end
|
95
102
|
end
|
96
103
|
assert(ok)
|
97
|
-
assert_equal(0, fb.query('(eq hello
|
104
|
+
assert_equal(0, fb.query('(eq hello $v)').each(v: 42).to_a.size)
|
98
105
|
end
|
99
106
|
end
|
data/test/factbase/test_tee.rb
CHANGED
@@ -40,4 +40,14 @@ class TestTee < Minitest::Test
|
|
40
40
|
assert_equal(42, t.foo)
|
41
41
|
assert_equal([13], t['$bar'])
|
42
42
|
end
|
43
|
+
|
44
|
+
def test_recursively
|
45
|
+
map = {}
|
46
|
+
prim = Factbase::Fact.new(Mutex.new, map)
|
47
|
+
prim.foo = 42
|
48
|
+
t = Factbase::Tee.new(nil, { 'bar' => 7 })
|
49
|
+
assert_equal(7, t['$bar'])
|
50
|
+
t = Factbase::Tee.new(prim, t)
|
51
|
+
assert_equal(7, t['$bar'])
|
52
|
+
end
|
43
53
|
end
|
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.52
|
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-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|