factbase 0.9.5 → 0.9.6
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/.rubocop.yml +4 -2
- data/.rultor.yml +1 -0
- data/Gemfile +9 -9
- data/Gemfile.lock +31 -127
- data/README.md +25 -24
- data/Rakefile +7 -14
- data/factbase.gemspec +6 -5
- data/lib/factbase/cached/cached_query.rb +1 -1
- data/lib/factbase/fact.rb +0 -5
- data/lib/factbase/indexed/indexed_term.rb +71 -10
- data/lib/factbase/logged.rb +18 -30
- data/lib/factbase/rules.rb +1 -1
- data/lib/factbase/taped.rb +4 -1
- data/lib/factbase/term.rb +1 -0
- data/lib/factbase.rb +1 -1
- data/test/factbase/cached/test_cached_query.rb +21 -0
- data/test/factbase/indexed/test_indexed_term.rb +10 -2
- data/test/factbase/test_logged.rb +6 -0
- data/test/factbase/test_query.rb +81 -6
- data/test/factbase/test_taped.rb +12 -0
- data/test/factbase/test_term.rb +2 -0
- metadata +36 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab2bcf895fa6934620163134f67815a20126515fcc163bdf7a232752a474bfcd
|
4
|
+
data.tar.gz: 2b96185e57e1ffa3176d34839940cff0a025b4cef8c7cd49b99bf9bdc79ab05c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac68811b7e3fd879a0a19079c537d5718095e0f8786de51b9fa949a1541f518dbd0f93ea9aedd749b41e90c965a9f81ec1fdd75b24e1959c0adc818d899f8017
|
7
|
+
data.tar.gz: dd39f0a82dc183b2c324660f1a9bb3ba6bf95cb2fa37c528d2684197aa96167dc62d6ee4797efd20c705a8c530c6e8ae09f332954023b1791c4dcb806f7b9a54
|
data/.rubocop.yml
CHANGED
@@ -20,6 +20,8 @@ Gemspec/RequiredRubyVersion:
|
|
20
20
|
Enabled: false
|
21
21
|
Metrics/MethodLength:
|
22
22
|
Enabled: false
|
23
|
+
Metrics/ModuleLength:
|
24
|
+
Enabled: false
|
23
25
|
Style/ClassAndModuleChildren:
|
24
26
|
Enabled: false
|
25
27
|
Layout/MultilineMethodCallIndentation:
|
@@ -29,9 +31,9 @@ Metrics/AbcSize:
|
|
29
31
|
Metrics/BlockLength:
|
30
32
|
Max: 50
|
31
33
|
Metrics/CyclomaticComplexity:
|
32
|
-
Max:
|
34
|
+
Max: 100
|
33
35
|
Metrics/PerceivedComplexity:
|
34
|
-
Max:
|
36
|
+
Max: 100
|
35
37
|
Metrics/ClassLength:
|
36
38
|
Enabled: false
|
37
39
|
Layout/EmptyLineAfterGuardClause:
|
data/.rultor.yml
CHANGED
data/Gemfile
CHANGED
@@ -6,18 +6,18 @@
|
|
6
6
|
source 'https://rubygems.org'
|
7
7
|
gemspec
|
8
8
|
|
9
|
-
gem 'minitest', '5.25
|
10
|
-
gem 'minitest-reporters', '1.7
|
9
|
+
gem 'minitest', '~>5.25', require: false
|
10
|
+
gem 'minitest-reporters', '~>1.7', require: false
|
11
11
|
gem 'os', '>0', require: false
|
12
12
|
gem 'qbash', '>0', require: false
|
13
|
-
gem 'rake', '13.2
|
14
|
-
gem '
|
15
|
-
gem 'rubocop', '1.74
|
13
|
+
gem 'rake', '~>13.2', require: false
|
14
|
+
gem 'rdoc', '~>6.13', require: false
|
15
|
+
gem 'rubocop', '~>1.74', require: false
|
16
16
|
gem 'rubocop-minitest', '>0', require: false
|
17
17
|
gem 'rubocop-performance', '>0', require: false
|
18
18
|
gem 'rubocop-rake', '>0', require: false
|
19
19
|
gem 'rubocop-rspec', '>0', require: false
|
20
|
-
gem 'simplecov', '0.22
|
21
|
-
gem 'simplecov-cobertura', '2.1
|
22
|
-
gem 'threads', '0.4
|
23
|
-
gem 'yard', '0.9
|
20
|
+
gem 'simplecov', '~>0.22', require: false
|
21
|
+
gem 'simplecov-cobertura', '~>2.1', require: false
|
22
|
+
gem 'threads', '~>0.4', require: false
|
23
|
+
gem 'yard', '~>0.9', require: false
|
data/Gemfile.lock
CHANGED
@@ -2,80 +2,34 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
factbase (0.0.0)
|
5
|
-
backtrace (
|
6
|
-
decoor (
|
5
|
+
backtrace (~> 0.4)
|
6
|
+
decoor (~> 0.0)
|
7
7
|
json (~> 2.7)
|
8
|
-
|
8
|
+
logger (~> 1.0)
|
9
|
+
loog (~> 0.6)
|
9
10
|
nokogiri (~> 1.10)
|
10
|
-
others (
|
11
|
-
tago (
|
11
|
+
others (~> 0.0)
|
12
|
+
tago (~> 0.0)
|
12
13
|
yaml (~> 0.3)
|
13
14
|
|
14
15
|
GEM
|
15
16
|
remote: https://rubygems.org/
|
16
17
|
specs:
|
17
|
-
actionpack (8.0.2)
|
18
|
-
actionview (= 8.0.2)
|
19
|
-
activesupport (= 8.0.2)
|
20
|
-
nokogiri (>= 1.8.5)
|
21
|
-
rack (>= 2.2.4)
|
22
|
-
rack-session (>= 1.0.1)
|
23
|
-
rack-test (>= 0.6.3)
|
24
|
-
rails-dom-testing (~> 2.2)
|
25
|
-
rails-html-sanitizer (~> 1.6)
|
26
|
-
useragent (~> 0.16)
|
27
|
-
actionview (8.0.2)
|
28
|
-
activesupport (= 8.0.2)
|
29
|
-
builder (~> 3.1)
|
30
|
-
erubi (~> 1.11)
|
31
|
-
rails-dom-testing (~> 2.2)
|
32
|
-
rails-html-sanitizer (~> 1.6)
|
33
|
-
activesupport (8.0.2)
|
34
|
-
base64
|
35
|
-
benchmark (>= 0.3)
|
36
|
-
bigdecimal
|
37
|
-
concurrent-ruby (~> 1.0, >= 1.3.1)
|
38
|
-
connection_pool (>= 2.2.5)
|
39
|
-
drb
|
40
|
-
i18n (>= 1.6, < 2)
|
41
|
-
logger (>= 1.4.2)
|
42
|
-
minitest (>= 5.1)
|
43
|
-
securerandom (>= 0.3)
|
44
|
-
tzinfo (~> 2.0, >= 2.0.5)
|
45
|
-
uri (>= 0.13.1)
|
46
18
|
ansi (1.5.0)
|
47
|
-
ast (2.4.
|
19
|
+
ast (2.4.3)
|
48
20
|
backtrace (0.4.0)
|
49
|
-
base64 (0.2.0)
|
50
|
-
benchmark (0.4.0)
|
51
|
-
bigdecimal (3.1.9)
|
52
21
|
builder (3.3.0)
|
53
22
|
concurrent-ruby (1.3.5)
|
54
|
-
connection_pool (2.5.0)
|
55
|
-
crass (1.0.6)
|
56
23
|
date (3.4.1)
|
57
24
|
decoor (0.0.1)
|
58
|
-
diff-lcs (1.6.0)
|
59
25
|
docile (1.4.1)
|
60
|
-
drb (2.2.1)
|
61
26
|
elapsed (0.0.1)
|
62
27
|
loog (> 0)
|
63
28
|
tago (> 0)
|
64
|
-
erubi (1.13.1)
|
65
|
-
i18n (1.14.7)
|
66
|
-
concurrent-ruby (~> 1.0)
|
67
|
-
io-console (0.8.0)
|
68
|
-
irb (1.15.1)
|
69
|
-
pp (>= 0.6.0)
|
70
|
-
rdoc (>= 4.0.0)
|
71
|
-
reline (>= 0.4.2)
|
72
29
|
json (2.10.2)
|
73
30
|
language_server-protocol (3.17.0.4)
|
74
31
|
lint_roller (1.1.0)
|
75
|
-
logger (1.
|
76
|
-
loofah (2.24.0)
|
77
|
-
crass (~> 1.0.2)
|
78
|
-
nokogiri (>= 1.12.0)
|
32
|
+
logger (1.7.0)
|
79
33
|
loog (0.6.0)
|
80
34
|
minitest (5.25.5)
|
81
35
|
minitest-reporters (1.7.1)
|
@@ -83,23 +37,21 @@ GEM
|
|
83
37
|
builder
|
84
38
|
minitest (>= 5.0)
|
85
39
|
ruby-progressbar
|
86
|
-
nokogiri (1.18.
|
40
|
+
nokogiri (1.18.6-arm64-darwin)
|
87
41
|
racc (~> 1.4)
|
88
|
-
nokogiri (1.18.
|
42
|
+
nokogiri (1.18.6-x64-mingw-ucrt)
|
89
43
|
racc (~> 1.4)
|
90
|
-
nokogiri (1.18.
|
44
|
+
nokogiri (1.18.6-x86_64-darwin)
|
91
45
|
racc (~> 1.4)
|
92
|
-
nokogiri (1.18.
|
46
|
+
nokogiri (1.18.6-x86_64-linux-gnu)
|
93
47
|
racc (~> 1.4)
|
94
48
|
os (1.1.4)
|
95
49
|
others (0.0.3)
|
96
50
|
parallel (1.26.3)
|
97
|
-
parser (3.3.7.
|
51
|
+
parser (3.3.7.3)
|
98
52
|
ast (~> 2.4.1)
|
99
53
|
racc
|
100
|
-
|
101
|
-
prettyprint
|
102
|
-
prettyprint (0.2.0)
|
54
|
+
prism (1.4.0)
|
103
55
|
psych (5.2.3)
|
104
56
|
date
|
105
57
|
stringio
|
@@ -109,55 +61,13 @@ GEM
|
|
109
61
|
loog (> 0)
|
110
62
|
tago (> 0)
|
111
63
|
racc (1.8.1)
|
112
|
-
rack (3.1.12)
|
113
|
-
rack-session (2.1.0)
|
114
|
-
base64 (>= 0.1.0)
|
115
|
-
rack (>= 3.0.0)
|
116
|
-
rack-test (2.2.0)
|
117
|
-
rack (>= 1.3)
|
118
|
-
rackup (2.2.1)
|
119
|
-
rack (>= 3)
|
120
|
-
rails-dom-testing (2.2.0)
|
121
|
-
activesupport (>= 5.0.0)
|
122
|
-
minitest
|
123
|
-
nokogiri (>= 1.6)
|
124
|
-
rails-html-sanitizer (1.6.2)
|
125
|
-
loofah (~> 2.21)
|
126
|
-
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
127
|
-
railties (8.0.2)
|
128
|
-
actionpack (= 8.0.2)
|
129
|
-
activesupport (= 8.0.2)
|
130
|
-
irb (~> 1.13)
|
131
|
-
rackup (>= 1.0.0)
|
132
|
-
rake (>= 12.2)
|
133
|
-
thor (~> 1.0, >= 1.2.2)
|
134
|
-
zeitwerk (~> 2.6)
|
135
64
|
rainbow (3.1.1)
|
136
65
|
rake (13.2.1)
|
137
|
-
rdoc (6.
|
66
|
+
rdoc (6.13.1)
|
138
67
|
psych (>= 4.0.0)
|
139
68
|
regexp_parser (2.10.0)
|
140
|
-
reline (0.6.0)
|
141
|
-
io-console (~> 0.5)
|
142
69
|
rexml (3.4.1)
|
143
|
-
|
144
|
-
rspec-support (~> 3.13.0)
|
145
|
-
rspec-expectations (3.13.3)
|
146
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
147
|
-
rspec-support (~> 3.13.0)
|
148
|
-
rspec-mocks (3.13.2)
|
149
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
150
|
-
rspec-support (~> 3.13.0)
|
151
|
-
rspec-rails (7.1.1)
|
152
|
-
actionpack (>= 7.0)
|
153
|
-
activesupport (>= 7.0)
|
154
|
-
railties (>= 7.0)
|
155
|
-
rspec-core (~> 3.13)
|
156
|
-
rspec-expectations (~> 3.13)
|
157
|
-
rspec-mocks (~> 3.13)
|
158
|
-
rspec-support (~> 3.13)
|
159
|
-
rspec-support (3.13.2)
|
160
|
-
rubocop (1.74.0)
|
70
|
+
rubocop (1.75.1)
|
161
71
|
json (~> 2.3)
|
162
72
|
language_server-protocol (~> 3.17.0.2)
|
163
73
|
lint_roller (~> 1.1.0)
|
@@ -165,11 +75,12 @@ GEM
|
|
165
75
|
parser (>= 3.3.0.2)
|
166
76
|
rainbow (>= 2.2.2, < 4.0)
|
167
77
|
regexp_parser (>= 2.9.3, < 3.0)
|
168
|
-
rubocop-ast (>= 1.
|
78
|
+
rubocop-ast (>= 1.43.0, < 2.0)
|
169
79
|
ruby-progressbar (~> 1.7)
|
170
80
|
unicode-display_width (>= 2.4.0, < 4.0)
|
171
|
-
rubocop-ast (1.
|
172
|
-
parser (>= 3.3.
|
81
|
+
rubocop-ast (1.43.0)
|
82
|
+
parser (>= 3.3.7.2)
|
83
|
+
prism (~> 1.4)
|
173
84
|
rubocop-minitest (0.37.1)
|
174
85
|
lint_roller (~> 1.1)
|
175
86
|
rubocop (>= 1.72.1, < 2.0)
|
@@ -185,7 +96,6 @@ GEM
|
|
185
96
|
lint_roller (~> 1.1)
|
186
97
|
rubocop (~> 1.72, >= 1.72.1)
|
187
98
|
ruby-progressbar (1.13.0)
|
188
|
-
securerandom (0.4.1)
|
189
99
|
simplecov (0.22.0)
|
190
100
|
docile (~> 1.1)
|
191
101
|
simplecov-html (~> 0.11)
|
@@ -195,22 +105,16 @@ GEM
|
|
195
105
|
simplecov (~> 0.19)
|
196
106
|
simplecov-html (0.13.1)
|
197
107
|
simplecov_json_formatter (0.1.4)
|
198
|
-
stringio (3.1.
|
199
|
-
tago (0.0
|
200
|
-
thor (1.3.2)
|
108
|
+
stringio (3.1.6)
|
109
|
+
tago (0.1.0)
|
201
110
|
threads (0.4.1)
|
202
111
|
backtrace (~> 0)
|
203
112
|
concurrent-ruby (~> 1.0)
|
204
|
-
tzinfo (2.0.6)
|
205
|
-
concurrent-ruby (~> 1.0)
|
206
113
|
unicode-display_width (3.1.4)
|
207
114
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
208
115
|
unicode-emoji (4.0.4)
|
209
|
-
uri (1.0.3)
|
210
|
-
useragent (0.16.11)
|
211
116
|
yaml (0.4.0)
|
212
117
|
yard (0.9.37)
|
213
|
-
zeitwerk (2.7.2)
|
214
118
|
|
215
119
|
PLATFORMS
|
216
120
|
arm64-darwin-22
|
@@ -223,21 +127,21 @@ PLATFORMS
|
|
223
127
|
|
224
128
|
DEPENDENCIES
|
225
129
|
factbase!
|
226
|
-
minitest (
|
227
|
-
minitest-reporters (
|
130
|
+
minitest (~> 5.25)
|
131
|
+
minitest-reporters (~> 1.7)
|
228
132
|
os (> 0)
|
229
133
|
qbash (> 0)
|
230
|
-
rake (
|
231
|
-
|
232
|
-
rubocop (
|
134
|
+
rake (~> 13.2)
|
135
|
+
rdoc (~> 6.13)
|
136
|
+
rubocop (~> 1.74)
|
233
137
|
rubocop-minitest (> 0)
|
234
138
|
rubocop-performance (> 0)
|
235
139
|
rubocop-rake (> 0)
|
236
140
|
rubocop-rspec (> 0)
|
237
|
-
simplecov (
|
238
|
-
simplecov-cobertura (
|
239
|
-
threads (
|
240
|
-
yard (
|
141
|
+
simplecov (~> 0.22)
|
142
|
+
simplecov-cobertura (~> 2.1)
|
143
|
+
threads (~> 0.4)
|
144
|
+
yard (~> 0.9)
|
241
145
|
|
242
146
|
BUNDLED WITH
|
243
147
|
2.5.16
|
data/README.md
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
[](http://rubydoc.info/github/yegor256/factbase/master/frames)
|
11
11
|
[](https://hitsofcode.com/view/github/yegor256/factbase)
|
12
12
|
[](https://github.com/yegor256/factbase/blob/master/LICENSE.txt)
|
13
|
+
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fyegor256%2Ffactbase?ref=badge_shield&issueType=license)
|
13
14
|
|
14
15
|
This Ruby gem manages an in-memory database of facts.
|
15
16
|
A fact is simply a map of properties and values.
|
@@ -209,33 +210,33 @@ This is the result of the benchmark:
|
|
209
210
|
<!-- benchmark_begin -->
|
210
211
|
```text
|
211
212
|
user system total real
|
212
|
-
insert 20000 facts 0.
|
213
|
-
export 20000 facts 0.
|
214
|
-
import
|
215
|
-
insert 10 facts 0.
|
216
|
-
query 10 times w/txn 1.
|
217
|
-
query 10 times w/o txn 0.
|
218
|
-
modify 10 attrs w/txn 1.
|
219
|
-
delete 10 facts w/txn 0.
|
220
|
-
(and (eq what 'issue-was-closed') (exists... -> 200
|
221
|
-
(and (eq what 'issue-was-closed') (exists... -> 200/txn
|
222
|
-
(and (eq what 'issue-was-closed') (exists... -> zero
|
223
|
-
(and (eq what 'issue-was-closed') (exists... -> zero/txn
|
224
|
-
(gt time '2024-03-23T03:21:43Z') 0.
|
225
|
-
(gt cost 50) 0.
|
226
|
-
(eq title 'Object Thinking 5000') 0.
|
227
|
-
(and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.
|
228
|
-
(eq id (agg (always) (max id))) 0.
|
229
|
-
(join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.
|
230
|
-
delete! 0.
|
231
|
-
Taped.append() x50000 0.
|
232
|
-
Taped.each() x125 1.
|
233
|
-
Taped.delete_if() x375 0.
|
213
|
+
insert 20000 facts 0.597725 0.004012 0.601737 ( 0.601785)
|
214
|
+
export 20000 facts 0.020481 0.003039 0.023520 ( 0.023523)
|
215
|
+
import 410961 bytes (20000 facts) 0.021204 0.002017 0.023221 ( 0.023223)
|
216
|
+
insert 10 facts 0.042456 0.002961 0.045417 ( 0.045418)
|
217
|
+
query 10 times w/txn 1.594704 0.026991 1.621695 ( 1.621807)
|
218
|
+
query 10 times w/o txn 0.057308 0.000013 0.057321 ( 0.057322)
|
219
|
+
modify 10 attrs w/txn 1.225101 0.013972 1.239073 ( 1.239349)
|
220
|
+
delete 10 facts w/txn 0.735944 0.001018 0.736962 ( 0.737102)
|
221
|
+
(and (eq what 'issue-was-closed') (exists... -> 200 2.068974 0.008005 2.076979 ( 2.077134)
|
222
|
+
(and (eq what 'issue-was-closed') (exists... -> 200/txn 1.094799 0.000000 1.094799 ( 1.094849)
|
223
|
+
(and (eq what 'issue-was-closed') (exists... -> zero 2.384214 0.001004 2.385218 ( 2.385610)
|
224
|
+
(and (eq what 'issue-was-closed') (exists... -> zero/txn 1.255267 0.001916 1.257183 ( 1.257310)
|
225
|
+
(gt time '2024-03-23T03:21:43Z') 0.110972 0.002000 0.112972 ( 0.112986)
|
226
|
+
(gt cost 50) 0.087402 0.000000 0.087402 ( 0.087411)
|
227
|
+
(eq title 'Object Thinking 5000') 0.002488 0.000000 0.002488 ( 0.002488)
|
228
|
+
(and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.022121 0.000001 0.022122 ( 0.022123)
|
229
|
+
(eq id (agg (always) (max id))) 0.237595 0.000000 0.237595 ( 0.237605)
|
230
|
+
(join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.635953 0.003996 0.639949 ( 0.640016)
|
231
|
+
delete! 0.060744 0.000997 0.061741 ( 0.061741)
|
232
|
+
Taped.append() x50000 0.037044 0.002000 0.039044 ( 0.039048)
|
233
|
+
Taped.each() x125 1.259629 0.002997 1.262626 ( 1.262661)
|
234
|
+
Taped.delete_if() x375 0.810420 0.000005 0.810425 ( 0.810483)
|
234
235
|
```
|
235
236
|
|
236
237
|
The results were calculated in [this GHA job][benchmark-gha]
|
237
|
-
on 2025-03-
|
238
|
+
on 2025-03-30 at 05:03,
|
238
239
|
on Linux with 4 CPUs.
|
239
240
|
<!-- benchmark_end -->
|
240
241
|
|
241
|
-
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/
|
242
|
+
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/14152813171
|
data/Rakefile
CHANGED
@@ -3,12 +3,12 @@
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
|
+
require 'os'
|
6
7
|
require 'qbash'
|
7
|
-
require 'rubygems'
|
8
8
|
require 'rake'
|
9
9
|
require 'rake/clean'
|
10
|
+
require 'rubygems'
|
10
11
|
require 'shellwords'
|
11
|
-
require 'os'
|
12
12
|
|
13
13
|
def name
|
14
14
|
@name ||= File.basename(Dir['*.gemspec'].first, '.*')
|
@@ -18,7 +18,7 @@ def version
|
|
18
18
|
Gem::Specification.load(Dir['*.gemspec'].first).version
|
19
19
|
end
|
20
20
|
|
21
|
-
task default: %i[clean test picks
|
21
|
+
task default: %i[clean test picks rubocop yard]
|
22
22
|
|
23
23
|
require 'rake/testtask'
|
24
24
|
desc 'Run all unit tests'
|
@@ -33,16 +33,10 @@ end
|
|
33
33
|
desc 'Run them via Ruby, one by one'
|
34
34
|
task :picks do
|
35
35
|
next if OS.windows?
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
desc 'Require them via Ruby, one by one'
|
42
|
-
task :reqs do
|
43
|
-
next if OS.windows?
|
44
|
-
Dir['lib/**/*.rb'].each do |f|
|
45
|
-
qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout)
|
36
|
+
%w[text lib].each do |d|
|
37
|
+
Dir["#{d}/**/*.rb"].each do |f|
|
38
|
+
qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout)
|
39
|
+
end
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
@@ -56,7 +50,6 @@ require 'rubocop/rake_task'
|
|
56
50
|
desc 'Run RuboCop on all directories'
|
57
51
|
RuboCop::RakeTask.new(:rubocop) do |task|
|
58
52
|
task.fail_on_error = true
|
59
|
-
task.requires << 'rubocop-rspec'
|
60
53
|
end
|
61
54
|
|
62
55
|
desc 'Benchmark them all'
|
data/factbase.gemspec
CHANGED
@@ -25,13 +25,14 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.files = `git ls-files`.split($RS)
|
26
26
|
s.rdoc_options = ['--charset=UTF-8']
|
27
27
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
28
|
-
s.add_dependency 'backtrace', '
|
29
|
-
s.add_dependency 'decoor', '
|
28
|
+
s.add_dependency 'backtrace', '~>0.4'
|
29
|
+
s.add_dependency 'decoor', '~>0.0'
|
30
30
|
s.add_dependency 'json', '~>2.7'
|
31
|
-
s.add_dependency '
|
31
|
+
s.add_dependency 'logger', '~>1.0'
|
32
|
+
s.add_dependency 'loog', '~>0.6'
|
32
33
|
s.add_dependency 'nokogiri', '~>1.10'
|
33
|
-
s.add_dependency 'others', '
|
34
|
-
s.add_dependency 'tago', '
|
34
|
+
s.add_dependency 'others', '~>0.0'
|
35
|
+
s.add_dependency 'tago', '~>0.0'
|
35
36
|
s.add_dependency 'yaml', '~>0.3'
|
36
37
|
s.metadata['rubygems_mfa_required'] = 'true'
|
37
38
|
end
|
@@ -43,7 +43,7 @@ class Factbase::CachedQuery
|
|
43
43
|
|
44
44
|
# Read a single value.
|
45
45
|
# @param [Hash] fb The factbase
|
46
|
-
# @param [Hash]
|
46
|
+
# @param [Hash] params Optional params accessible in the query via the "$" symbol (unused)
|
47
47
|
# @return The value evaluated
|
48
48
|
def one(fb = @fb, params = {})
|
49
49
|
key = "one: #{@origin} #{params}"
|
data/lib/factbase/fact.rb
CHANGED
@@ -46,11 +46,6 @@ class Factbase::Fact
|
|
46
46
|
@map.keys
|
47
47
|
end
|
48
48
|
|
49
|
-
# When a method is missing, this method is called.
|
50
|
-
# Method missing handler for dynamic property access and setting
|
51
|
-
# @param [Symbol] method The method name being called
|
52
|
-
# @param [Array] args Method arguments
|
53
|
-
# @return [Object] The value retrieved or nil if setting a value
|
54
49
|
others do |*args|
|
55
50
|
k = args[0].to_s
|
56
51
|
if k.end_with?('=')
|
@@ -68,18 +68,45 @@ module Factbase::IndexedTerm
|
|
68
68
|
end
|
69
69
|
when :and
|
70
70
|
r = nil
|
71
|
-
@operands.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
if @operands.all? { |o| o.op == :eq } && @operands.size > 1 \
|
72
|
+
&& @operands.all? { |o| o.operands.first.is_a?(Symbol) && _scalar?(o.operands[1]) }
|
73
|
+
key = [maps.object_id, @operands.map { |o| o.operands.first }, :multi_eq]
|
74
|
+
props = @operands.map { |o| o.operands.first }.sort
|
75
|
+
if @idx[key].nil?
|
76
|
+
@idx[key] = {}
|
77
|
+
maps.to_a.each do |m|
|
78
|
+
_all_tuples(m, props).each do |t|
|
79
|
+
@idx[key][t] = [] if @idx[key][t].nil?
|
80
|
+
@idx[key][t].append(m)
|
81
|
+
end
|
82
|
+
end
|
76
83
|
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
84
|
+
tuples = _as_tuples(
|
85
|
+
@operands.sort_by { |o| o.operands.first }.map do |o|
|
86
|
+
if o.operands[1].is_a?(Symbol)
|
87
|
+
sym = o.operands[1].to_s.gsub(/^\$/, '')
|
88
|
+
params[sym] || []
|
89
|
+
else
|
90
|
+
[o.operands[1]]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
)
|
94
|
+
j = tuples.map { |t| @idx[key][t] || [] }.reduce(&:|)
|
95
|
+
r = (maps & []) | j
|
96
|
+
else
|
97
|
+
@operands.each do |o|
|
98
|
+
n = o.predict(maps, params)
|
99
|
+
if n.nil?
|
100
|
+
r = nil
|
101
|
+
break
|
102
|
+
end
|
103
|
+
if r.nil?
|
104
|
+
r = n
|
105
|
+
else
|
106
|
+
r &= n.to_a
|
107
|
+
end
|
108
|
+
break if r.empty?
|
81
109
|
end
|
82
|
-
break if r.empty?
|
83
110
|
end
|
84
111
|
r
|
85
112
|
when :or
|
@@ -106,6 +133,40 @@ module Factbase::IndexedTerm
|
|
106
133
|
|
107
134
|
private
|
108
135
|
|
136
|
+
# The input looks like this: [[6, 55], [3], [4, 3, 5]].
|
137
|
+
# The outputh should contain all possible combinations: [[6, 3, 4], [6, 3, 3], [55, 3, 5], ...]
|
138
|
+
def _as_tuples(values)
|
139
|
+
tuples = [values.first]
|
140
|
+
if values.size > 1
|
141
|
+
tails = _as_tuples(values[1..])
|
142
|
+
ext = []
|
143
|
+
tuples.each do |t|
|
144
|
+
tails.each do |tail|
|
145
|
+
ext << (t + tail)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
tuples = ext
|
149
|
+
end
|
150
|
+
tuples
|
151
|
+
end
|
152
|
+
|
153
|
+
def _all_tuples(fact, props)
|
154
|
+
prop = props.first.to_s
|
155
|
+
tuples = []
|
156
|
+
tuples += (fact[prop] || []).zip
|
157
|
+
if props.size > 1
|
158
|
+
tails = _all_tuples(fact, props[1..])
|
159
|
+
ext = []
|
160
|
+
tuples.each do |t|
|
161
|
+
tails.each do |tail|
|
162
|
+
ext << (t + tail)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
tuples = ext
|
166
|
+
end
|
167
|
+
tuples
|
168
|
+
end
|
169
|
+
|
109
170
|
def _scalar?(item)
|
110
171
|
item.is_a?(String) || item.is_a?(Time) || item.is_a?(Integer) || item.is_a?(Float) || item.is_a?(Symbol)
|
111
172
|
end
|
data/lib/factbase/logged.rb
CHANGED
@@ -131,47 +131,35 @@ class Factbase::Logged
|
|
131
131
|
@fb = fb
|
132
132
|
end
|
133
133
|
|
134
|
-
def
|
134
|
+
def to_s
|
135
|
+
@term.to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
def each(fb = @fb, params = {}, &)
|
135
139
|
return to_enum(__method__, fb, params) unless block_given?
|
136
140
|
start = Time.now
|
137
141
|
q = Factbase::Syntax.new(@term).to_term.to_s
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
r = @fb.query(@term, @maps).each(@fb, params, &)
|
143
|
-
end
|
144
|
-
raise ".each of #{@term.class} returned #{r.class}" unless r.is_a?(Integer)
|
145
|
-
if r.zero?
|
146
|
-
@tube.say(start, "Zero/#{@fb.size} facts found by '#{q}' #{tail}")
|
147
|
-
else
|
148
|
-
@tube.say(start, "Found #{r}/#{@fb.size} fact(s) by '#{q}' #{tail}")
|
142
|
+
r = nil
|
143
|
+
tail =
|
144
|
+
Factbase::Logged.elapsed do
|
145
|
+
r = @fb.query(@term, @maps).each(fb, params, &)
|
149
146
|
end
|
150
|
-
|
147
|
+
raise ".each of #{@term.class} returned #{r.class}" unless r.is_a?(Integer)
|
148
|
+
if r.zero?
|
149
|
+
@tube.say(start, "Zero/#{@fb.size} facts found by '#{q}' #{tail}")
|
151
150
|
else
|
152
|
-
|
153
|
-
tail =
|
154
|
-
Factbase::Logged.elapsed do
|
155
|
-
@fb.query(@term, @maps).each(@fb, params) do |f|
|
156
|
-
array << f
|
157
|
-
end
|
158
|
-
end
|
159
|
-
if array.empty?
|
160
|
-
@tube.say(start, "Zero/#{@fb.size} found by '#{q}' #{tail}")
|
161
|
-
else
|
162
|
-
@tube.say(start, "Found #{array.size}/#{@fb.size} fact(s) by '#{q}' #{tail}")
|
163
|
-
end
|
164
|
-
array
|
151
|
+
@tube.say(start, "Found #{r}/#{@fb.size} fact(s) by '#{q}' #{tail}")
|
165
152
|
end
|
153
|
+
r
|
166
154
|
end
|
167
155
|
|
168
|
-
def one(
|
156
|
+
def one(fb = @fb, params = {})
|
169
157
|
start = Time.now
|
170
158
|
q = Factbase::Syntax.new(@term).to_term.to_s
|
171
159
|
r = nil
|
172
160
|
tail =
|
173
161
|
Factbase::Logged.elapsed do
|
174
|
-
r = @fb.query(@term, @maps).one(
|
162
|
+
r = @fb.query(@term, @maps).one(fb, params)
|
175
163
|
end
|
176
164
|
if r.nil?
|
177
165
|
@tube.say(start, "Nothing found by '#{q}' #{tail}")
|
@@ -181,13 +169,13 @@ class Factbase::Logged
|
|
181
169
|
r
|
182
170
|
end
|
183
171
|
|
184
|
-
def delete!(
|
172
|
+
def delete!(fb = @fb)
|
185
173
|
r = nil
|
186
174
|
start = Time.now
|
187
175
|
before = @fb.size
|
188
176
|
tail =
|
189
177
|
Factbase::Logged.elapsed do
|
190
|
-
r = @fb.query(@term).delete!(
|
178
|
+
r = @fb.query(@term, @maps).delete!(fb)
|
191
179
|
end
|
192
180
|
raise ".delete! of #{@term.class} returned #{r.class}" unless r.is_a?(Integer)
|
193
181
|
if before.zero?
|
data/lib/factbase/rules.rb
CHANGED
data/lib/factbase/taped.rb
CHANGED
@@ -68,12 +68,15 @@ class Factbase::Taped
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def &(other)
|
71
|
-
|
71
|
+
if other == [] || @origin.empty?
|
72
|
+
return Factbase::Taped.new([], inserted: @inserted, deleted: @deleted, added: @added)
|
73
|
+
end
|
72
74
|
join(other, &:&)
|
73
75
|
end
|
74
76
|
|
75
77
|
def |(other)
|
76
78
|
return Factbase::Taped.new(to_a, inserted: @inserted, deleted: @deleted, added: @added) if other == []
|
79
|
+
return Factbase::Taped.new(other, inserted: @inserted, deleted: @deleted, added: @added) if @origin.empty?
|
77
80
|
join(other, &:|)
|
78
81
|
end
|
79
82
|
|
data/lib/factbase/term.rb
CHANGED
@@ -104,6 +104,7 @@ class Factbase::Term
|
|
104
104
|
# should be evaluated. If no prediction can be made,
|
105
105
|
# the same list is returned.
|
106
106
|
# @param [Array<Hash>] maps Records to iterate, maybe
|
107
|
+
# @param [Hash] _params Params to use (keys must be strings, not symbols, with values as arrays)
|
107
108
|
# @return [Array<Hash>] Records to iterate
|
108
109
|
def predict(maps, _params)
|
109
110
|
maps
|
data/lib/factbase.rb
CHANGED
@@ -82,7 +82,7 @@ require 'yaml'
|
|
82
82
|
# License:: MIT
|
83
83
|
class Factbase
|
84
84
|
# Current version of the gem (changed by .rultor.yml on every release)
|
85
|
-
VERSION = '0.9.
|
85
|
+
VERSION = '0.9.6' unless const_defined?(:VERSION)
|
86
86
|
|
87
87
|
# An exception that may be thrown in a transaction, to roll it back.
|
88
88
|
class Rollback < StandardError; end
|
@@ -3,8 +3,10 @@
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
|
+
require 'loog'
|
6
7
|
require_relative '../../test__helper'
|
7
8
|
require_relative '../../../lib/factbase'
|
9
|
+
require_relative '../../../lib/factbase/logged'
|
8
10
|
require_relative '../../../lib/factbase/cached/cached_factbase'
|
9
11
|
require_relative '../../../lib/factbase/indexed/indexed_factbase'
|
10
12
|
require_relative '../../../lib/factbase/sync/sync_factbase'
|
@@ -58,6 +60,25 @@ class TestCachedQuery < Factbase::Test
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
63
|
+
def test_works_with_logging
|
64
|
+
fb = Factbase::CachedFactbase.new(Factbase::Logged.new(Factbase.new, Loog::NULL))
|
65
|
+
total = 10
|
66
|
+
total.times do |i|
|
67
|
+
f = fb.insert
|
68
|
+
f.foo = i
|
69
|
+
f.hello = 1
|
70
|
+
end
|
71
|
+
3.times do
|
72
|
+
[
|
73
|
+
'(exists foo)',
|
74
|
+
'(and (gt foo -99) (exists hello))',
|
75
|
+
'(and (lt hello 1000.44) (exists foo) (not (exists bar)))'
|
76
|
+
].each do |q|
|
77
|
+
assert_equal(total, fb.query(q).each.to_a.size)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
61
82
|
def test_caches_while_being_decorated
|
62
83
|
fb = Factbase::SyncFactbase.new(Factbase::CachedFactbase.new(Factbase.new))
|
63
84
|
10_000.times do |i|
|
@@ -59,17 +59,25 @@ class TestIndexedTerm < Factbase::Test
|
|
59
59
|
:and,
|
60
60
|
[
|
61
61
|
Factbase::Term.new(:eq, [:foo, 42]),
|
62
|
-
Factbase::Term.new(:eq, [
|
62
|
+
Factbase::Term.new(:eq, %i[bar $a])
|
63
63
|
]
|
64
64
|
)
|
65
65
|
idx = {}
|
66
66
|
term.redress!(Factbase::IndexedTerm, idx:)
|
67
67
|
maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7], 'foo' => [22, 42] }, { 'foo' => [22, 42] }])
|
68
|
-
n = term.predict(maps, { a
|
68
|
+
n = term.predict(maps, { 'a' => [7] })
|
69
69
|
assert_equal(1, n.size)
|
70
70
|
assert_kind_of(Factbase::Taped, n)
|
71
71
|
end
|
72
72
|
|
73
|
+
def test_predicts_on_single_and
|
74
|
+
term = Factbase::Term.new(:and, [Factbase::Term.new(:eq, [:foo, 42])])
|
75
|
+
idx = {}
|
76
|
+
term.redress!(Factbase::IndexedTerm, idx:)
|
77
|
+
maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7], 'foo' => [4] }])
|
78
|
+
assert_equal(1, term.predict(maps, {}).size)
|
79
|
+
end
|
80
|
+
|
73
81
|
def test_predicts_on_or
|
74
82
|
term = Factbase::Term.new(
|
75
83
|
:or,
|
@@ -92,6 +92,12 @@ class TestLogged < Factbase::Test
|
|
92
92
|
assert_equal(0, Factbase::Logged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
|
93
93
|
end
|
94
94
|
|
95
|
+
def test_returns_to_s_correctly
|
96
|
+
fb = Factbase.new
|
97
|
+
q = '(always)'
|
98
|
+
assert_equal(q, fb.query(q).to_s)
|
99
|
+
end
|
100
|
+
|
95
101
|
def test_logs_when_enumerator
|
96
102
|
fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
|
97
103
|
assert_equal(0, fb.query('(always)').each.to_a.size)
|
data/test/factbase/test_query.rb
CHANGED
@@ -123,11 +123,13 @@ class TestQuery < Factbase::Test
|
|
123
123
|
{ 'num' => [42, 66, 0], 'pi' => [3.14], 'name' => ['peter'] },
|
124
124
|
{ 'num' => [0], 'time' => [Time.now - 100], 'hi' => [4], 'nome' => ['Walter'] }
|
125
125
|
]
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
126
|
+
3.times do |cycle|
|
127
|
+
with_factbases(maps) do |badge, fb|
|
128
|
+
queries.each do |q, r|
|
129
|
+
assert_equal(r, fb.query(q).each.to_a.size, "#{q} in #{badge} (cycle ##{cycle})")
|
130
|
+
fb.txn do |fbt|
|
131
|
+
assert_equal(r, fbt.query(q).each.to_a.size, "#{q} in #{badge} (txn, cycle ##{cycle})")
|
132
|
+
end
|
131
133
|
end
|
132
134
|
end
|
133
135
|
end
|
@@ -301,12 +303,85 @@ class TestQuery < Factbase::Test
|
|
301
303
|
'sync+plain' => Factbase::SyncFactbase.new(Factbase.new(maps)),
|
302
304
|
'tallied+plain' => Factbase::Tallied.new(Factbase.new(maps)),
|
303
305
|
'indexed+plain' => Factbase::IndexedFactbase.new(Factbase.new(maps)),
|
306
|
+
'indexed+logged+plain' => Factbase::IndexedFactbase.new(
|
307
|
+
Factbase::Logged.new(
|
308
|
+
Factbase.new(maps),
|
309
|
+
Loog::NULL
|
310
|
+
)
|
311
|
+
),
|
304
312
|
'cached+plain' => Factbase::CachedFactbase.new(Factbase.new(maps)),
|
313
|
+
'cached+logged+plain' => Factbase::CachedFactbase.new(
|
314
|
+
Factbase::Logged.new(
|
315
|
+
Factbase.new(maps),
|
316
|
+
Loog::NULL
|
317
|
+
)
|
318
|
+
),
|
305
319
|
'logged+plain' => Factbase::Logged.new(Factbase.new(maps), Loog::NULL),
|
306
320
|
'indexed+cached+plain' => Factbase::IndexedFactbase.new(Factbase::CachedFactbase.new(Factbase.new(maps))),
|
307
321
|
'cached+indexed+plain' => Factbase::CachedFactbase.new(Factbase::IndexedFactbase.new(Factbase.new(maps))),
|
322
|
+
'indexed+indexed+plain' => Factbase::IndexedFactbase.new(
|
323
|
+
Factbase::IndexedFactbase.new(Factbase.new(maps))
|
324
|
+
),
|
325
|
+
'cached+cached+cached+plain' => Factbase::CachedFactbase.new(
|
326
|
+
Factbase::CachedFactbase.new(
|
327
|
+
Factbase::CachedFactbase.new(
|
328
|
+
Factbase.new(maps)
|
329
|
+
)
|
330
|
+
)
|
331
|
+
),
|
332
|
+
'tallied+pre+rules+inv+plain' => Factbase::Tallied.new(
|
333
|
+
Factbase::Pre.new(
|
334
|
+
Factbase::Rules.new(
|
335
|
+
Factbase::Inv.new(
|
336
|
+
Factbase.new(maps)
|
337
|
+
) { nil },
|
338
|
+
'(always)'
|
339
|
+
)
|
340
|
+
) { nil }
|
341
|
+
),
|
308
342
|
'sync+cached+indexed+plain' => Factbase::SyncFactbase.new(
|
309
|
-
Factbase::CachedFactbase.new(
|
343
|
+
Factbase::CachedFactbase.new(
|
344
|
+
Factbase::IndexedFactbase.new(
|
345
|
+
Factbase.new(maps)
|
346
|
+
)
|
347
|
+
)
|
348
|
+
),
|
349
|
+
'sync+logged+plain' => Factbase::SyncFactbase.new(
|
350
|
+
Factbase::Logged.new(
|
351
|
+
Factbase.new(maps),
|
352
|
+
Loog::NULL
|
353
|
+
)
|
354
|
+
),
|
355
|
+
'sync+cached+indexed+logged+plain' => Factbase::SyncFactbase.new(
|
356
|
+
Factbase::CachedFactbase.new(
|
357
|
+
Factbase::IndexedFactbase.new(
|
358
|
+
Factbase::Logged.new(
|
359
|
+
Factbase.new(maps),
|
360
|
+
Loog::NULL
|
361
|
+
)
|
362
|
+
)
|
363
|
+
)
|
364
|
+
),
|
365
|
+
'sync+sync+sync+plain' => Factbase::SyncFactbase.new(
|
366
|
+
Factbase::SyncFactbase.new(
|
367
|
+
Factbase::SyncFactbase.new(
|
368
|
+
Factbase::SyncFactbase.new(
|
369
|
+
Factbase.new(maps)
|
370
|
+
)
|
371
|
+
)
|
372
|
+
)
|
373
|
+
),
|
374
|
+
'logged+logged+logged+plain' => Factbase::SyncFactbase.new(
|
375
|
+
Factbase::Logged.new(
|
376
|
+
Factbase::Logged.new(
|
377
|
+
Factbase::Logged.new(
|
378
|
+
Factbase.new(maps),
|
379
|
+
Loog::NULL
|
380
|
+
),
|
381
|
+
Loog::NULL
|
382
|
+
),
|
383
|
+
Loog::NULL
|
384
|
+
)
|
310
385
|
),
|
311
386
|
'all+plain' => Factbase::Tallied.new(
|
312
387
|
Factbase::Pre.new(
|
data/test/factbase/test_taped.rb
CHANGED
@@ -18,6 +18,18 @@ class TestTaped < Factbase::Test
|
|
18
18
|
assert_equal(1, t.inserted.size)
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_joins_with_empty
|
22
|
+
t = Factbase::Taped.new([{ foo: 'yes' }])
|
23
|
+
t &= []
|
24
|
+
assert_equal(0, t.size)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_disjoins_with_empty
|
28
|
+
t = Factbase::Taped.new([{ bar: 'oops' }])
|
29
|
+
t |= []
|
30
|
+
assert_equal(1, t.size)
|
31
|
+
end
|
32
|
+
|
21
33
|
def test_tracks_deletion
|
22
34
|
t = Factbase::Taped.new([{ x: 1 }, { x: 2 }])
|
23
35
|
t.delete_if { |m| m[:x] == 1 }
|
data/test/factbase/test_term.rb
CHANGED
@@ -81,5 +81,7 @@ class TestTerm < Factbase::Test
|
|
81
81
|
t.redress!(Factbase::IndexedTerm)
|
82
82
|
require_relative '../../lib/factbase/cached/cached_term'
|
83
83
|
t.redress!(Factbase::CachedTerm)
|
84
|
+
assert_kind_of(Factbase::CachedTerm, t)
|
85
|
+
refute_kind_of(Factbase::CachedTerm, Factbase::Term.new(:something, []))
|
84
86
|
end
|
85
87
|
end
|
metadata
CHANGED
@@ -1,42 +1,42 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03-
|
10
|
+
date: 2025-03-30 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: backtrace
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
|
-
- - "
|
16
|
+
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 0.4
|
18
|
+
version: '0.4'
|
19
19
|
type: :runtime
|
20
20
|
prerelease: false
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
22
22
|
requirements:
|
23
|
-
- - "
|
23
|
+
- - "~>"
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 0.4
|
25
|
+
version: '0.4'
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: decoor
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
|
-
- - "
|
30
|
+
- - "~>"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.0
|
32
|
+
version: '0.0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.0
|
39
|
+
version: '0.0'
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: json
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -51,20 +51,34 @@ dependencies:
|
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '2.7'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: logger
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.0'
|
54
68
|
- !ruby/object:Gem::Dependency
|
55
69
|
name: loog
|
56
70
|
requirement: !ruby/object:Gem::Requirement
|
57
71
|
requirements:
|
58
|
-
- - "
|
72
|
+
- - "~>"
|
59
73
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.6
|
74
|
+
version: '0.6'
|
61
75
|
type: :runtime
|
62
76
|
prerelease: false
|
63
77
|
version_requirements: !ruby/object:Gem::Requirement
|
64
78
|
requirements:
|
65
|
-
- - "
|
79
|
+
- - "~>"
|
66
80
|
- !ruby/object:Gem::Version
|
67
|
-
version: 0.6
|
81
|
+
version: '0.6'
|
68
82
|
- !ruby/object:Gem::Dependency
|
69
83
|
name: nokogiri
|
70
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -83,30 +97,30 @@ dependencies:
|
|
83
97
|
name: others
|
84
98
|
requirement: !ruby/object:Gem::Requirement
|
85
99
|
requirements:
|
86
|
-
- - "
|
100
|
+
- - "~>"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: 0.0
|
102
|
+
version: '0.0'
|
89
103
|
type: :runtime
|
90
104
|
prerelease: false
|
91
105
|
version_requirements: !ruby/object:Gem::Requirement
|
92
106
|
requirements:
|
93
|
-
- - "
|
107
|
+
- - "~>"
|
94
108
|
- !ruby/object:Gem::Version
|
95
|
-
version: 0.0
|
109
|
+
version: '0.0'
|
96
110
|
- !ruby/object:Gem::Dependency
|
97
111
|
name: tago
|
98
112
|
requirement: !ruby/object:Gem::Requirement
|
99
113
|
requirements:
|
100
|
-
- - "
|
114
|
+
- - "~>"
|
101
115
|
- !ruby/object:Gem::Version
|
102
|
-
version: 0.0
|
116
|
+
version: '0.0'
|
103
117
|
type: :runtime
|
104
118
|
prerelease: false
|
105
119
|
version_requirements: !ruby/object:Gem::Requirement
|
106
120
|
requirements:
|
107
|
-
- - "
|
121
|
+
- - "~>"
|
108
122
|
- !ruby/object:Gem::Version
|
109
|
-
version: 0.0
|
123
|
+
version: '0.0'
|
110
124
|
- !ruby/object:Gem::Dependency
|
111
125
|
name: yaml
|
112
126
|
requirement: !ruby/object:Gem::Requirement
|