factbase 0.0.7 → 0.0.9
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/factbase.gemspec +2 -1
- data/lib/factbase/fact.rb +21 -9
- data/lib/factbase/query.rb +0 -10
- data/lib/factbase/syntax.rb +3 -0
- data/lib/factbase/term.rb +4 -3
- data/lib/factbase.rb +14 -3
- data/test/factbase/test_fact.rb +24 -3
- data/test/factbase/test_syntax.rb +1 -0
- data/test/factbase/test_term.rb +4 -2
- data/test/test_factbase.rb +15 -1
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38ebbf43ee181a50bc4ca45d32ac3ba1394180e25ea719b41917606c2d00a6c9
|
4
|
+
data.tar.gz: f2e71d19bd3523a4db543b410989f88708e3120cbebde21682080b822e11c7d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 802e11490eda7455f3d00ecce17c70e73f6520c5f06a25ea1ad7393ceb98a8ca67858343d4ee544183f10b695c872f140855037f091623ba057296c755fe6c13
|
7
|
+
data.tar.gz: d58f72e6aeabd5e99fe7424c769f56074c2f9dc95593dd76c3373ee770dcfd96c1f05dd51731c25660bfcb2aedfde2ffe8f7842679e6e46ef95532b090c3428c
|
data/factbase.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
27
27
|
s.required_ruby_version = '>=2.3'
|
28
28
|
s.name = 'factbase'
|
29
|
-
s.version = '0.0.
|
29
|
+
s.version = '0.0.9'
|
30
30
|
s.license = 'MIT'
|
31
31
|
s.summary = 'Factbase'
|
32
32
|
s.description = 'Fact base in memory and on disc'
|
@@ -39,5 +39,6 @@ Gem::Specification.new do |s|
|
|
39
39
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
40
40
|
s.add_runtime_dependency 'json', '~> 2.7'
|
41
41
|
s.add_runtime_dependency 'nokogiri', '~> 1.10'
|
42
|
+
s.add_runtime_dependency 'yaml', '~> 0.3'
|
42
43
|
s.metadata['rubygems_mfa_required'] = 'true'
|
43
44
|
end
|
data/lib/factbase/fact.rb
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
|
+
require 'json'
|
23
24
|
require_relative '../factbase'
|
24
25
|
|
25
26
|
# Fact.
|
@@ -32,26 +33,37 @@ class Factbase::Fact
|
|
32
33
|
@map = map
|
33
34
|
end
|
34
35
|
|
36
|
+
def to_s
|
37
|
+
@map.to_json
|
38
|
+
end
|
39
|
+
|
35
40
|
def method_missing(*args)
|
36
41
|
k = args[0].to_s
|
37
42
|
if k.end_with?('=')
|
38
43
|
kk = k[0..-2]
|
39
44
|
raise "Invalid prop name '#{kk}'" unless kk.match?(/^[a-z][a-zA-Z0-9]+$/)
|
45
|
+
v = args[1]
|
46
|
+
raise "Prop value can't be empty" if v == ''
|
40
47
|
@mutex.synchronize do
|
41
|
-
|
42
|
-
|
48
|
+
before = @map[kk]
|
49
|
+
return if before == v
|
50
|
+
if before.nil?
|
51
|
+
@map[kk] = v
|
52
|
+
return
|
53
|
+
end
|
54
|
+
@map[kk] = [@map[kk]] unless @map[kk].is_a?(Array)
|
55
|
+
@map[kk] << v
|
43
56
|
end
|
44
57
|
nil
|
45
58
|
elsif k == '[]'
|
46
|
-
|
47
|
-
@mutex.synchronize do
|
48
|
-
@map[kk] = [] if @map[kk].nil?
|
49
|
-
end
|
50
|
-
@map[kk]
|
59
|
+
@map[args[1].to_s]
|
51
60
|
else
|
52
61
|
v = @map[k]
|
53
|
-
|
54
|
-
|
62
|
+
if v.nil?
|
63
|
+
raise "Can't get '#{k}', the fact is empty" if @map.empty?
|
64
|
+
raise "Can't find '#{k}' attribute in [#{@map.keys.join(', ')}]"
|
65
|
+
end
|
66
|
+
v.is_a?(Array) ? v[0] : v
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
data/lib/factbase/query.rb
CHANGED
@@ -45,14 +45,4 @@ class Factbase::Query
|
|
45
45
|
yield f
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
49
|
-
# Turn it into an array.
|
50
|
-
# @return [Array] All facts in an array
|
51
|
-
# rubocop:disable Style/MapIntoArray
|
52
|
-
def to_a
|
53
|
-
array = []
|
54
|
-
each { |f| array << f }
|
55
|
-
array
|
56
|
-
end
|
57
|
-
# rubocop:enable Style/MapIntoArray
|
58
48
|
end
|
data/lib/factbase/syntax.rb
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
|
+
require_relative '../factbase'
|
23
24
|
require_relative 'fact'
|
24
25
|
require_relative 'term'
|
25
26
|
|
@@ -72,6 +73,7 @@ class Factbase::Syntax
|
|
72
73
|
[Factbase::Term.new(op, operands), at + 1]
|
73
74
|
end
|
74
75
|
|
76
|
+
# Turns a query into an array of tokens.
|
75
77
|
def to_tokens
|
76
78
|
list = []
|
77
79
|
acc = ''
|
@@ -108,6 +110,7 @@ class Factbase::Syntax
|
|
108
110
|
if t.is_a?(Symbol)
|
109
111
|
t
|
110
112
|
elsif t.start_with?('\'', '"')
|
113
|
+
raise 'String literal can\'t be empty' if t.length <= 2
|
111
114
|
t[1..-2]
|
112
115
|
elsif t.match?(/^[0-9]+$/)
|
113
116
|
t.to_i
|
data/lib/factbase/term.rb
CHANGED
@@ -84,7 +84,7 @@ class Factbase::Term
|
|
84
84
|
def exists(fact)
|
85
85
|
assert_args(1)
|
86
86
|
k = @operands[0].to_s
|
87
|
-
!fact[k].
|
87
|
+
!fact[k].nil?
|
88
88
|
end
|
89
89
|
|
90
90
|
def absent(fact)
|
@@ -97,8 +97,9 @@ class Factbase::Term
|
|
97
97
|
assert_args(2)
|
98
98
|
k = @operands[0].to_s
|
99
99
|
v = fact[k]
|
100
|
-
return
|
101
|
-
v.include?(@operands[1])
|
100
|
+
return true if v == @operands[1]
|
101
|
+
return v.include?(@operands[1]) if v.is_a?(Array)
|
102
|
+
false
|
102
103
|
end
|
103
104
|
|
104
105
|
def lt(fact)
|
data/lib/factbase.rb
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'json'
|
24
24
|
require 'nokogiri'
|
25
|
+
require 'yaml'
|
25
26
|
|
26
27
|
# Factbase.
|
27
28
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
@@ -99,10 +100,14 @@ class Factbase
|
|
99
100
|
@maps.each do |m|
|
100
101
|
xml.f do
|
101
102
|
m.each do |k, vv|
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
if vv.is_a?(Array)
|
104
|
+
xml.send(:"#{k}") do
|
105
|
+
vv.each do |v|
|
106
|
+
xml.send(:v, v)
|
107
|
+
end
|
105
108
|
end
|
109
|
+
else
|
110
|
+
xml.send(:"#{k}", vv)
|
106
111
|
end
|
107
112
|
end
|
108
113
|
end
|
@@ -110,4 +115,10 @@ class Factbase
|
|
110
115
|
end
|
111
116
|
end.to_xml
|
112
117
|
end
|
118
|
+
|
119
|
+
# Convert the entire factbase into YAML.
|
120
|
+
# @return [String] The factbase in YAML format
|
121
|
+
def to_yaml
|
122
|
+
YAML.dump({ 'facts' => @maps })
|
123
|
+
end
|
113
124
|
end
|
data/test/factbase/test_fact.rb
CHANGED
@@ -33,9 +33,30 @@ class TestFact < Minitest::Test
|
|
33
33
|
map = {}
|
34
34
|
f = Factbase::Fact.new(Mutex.new, map)
|
35
35
|
f.foo = 42
|
36
|
-
assert_equal(42, f.foo)
|
36
|
+
assert_equal(42, f.foo, f.to_s)
|
37
37
|
f.foo = 256
|
38
|
-
assert_equal(42, f.foo)
|
39
|
-
assert_equal([42, 256], f['foo'])
|
38
|
+
assert_equal(42, f.foo, f.to_s)
|
39
|
+
assert_equal([42, 256], f['foo'], f.to_s)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_fails_when_empty
|
43
|
+
f = Factbase::Fact.new(Mutex.new, {})
|
44
|
+
assert_raises do
|
45
|
+
f.something
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_fails_when_not_found
|
50
|
+
f = Factbase::Fact.new(Mutex.new, {})
|
51
|
+
f.first = 42
|
52
|
+
assert_raises do
|
53
|
+
f.second
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_set_by_name
|
58
|
+
f = Factbase::Fact.new(Mutex.new, {})
|
59
|
+
f.send('foo=', 42)
|
60
|
+
assert_equal(42, f.foo, f.to_s)
|
40
61
|
end
|
41
62
|
end
|
data/test/factbase/test_term.rb
CHANGED
@@ -31,14 +31,16 @@ class TestTerm < Minitest::Test
|
|
31
31
|
def test_simple_matching
|
32
32
|
t = Factbase::Term.new(:eq, ['foo', 42])
|
33
33
|
assert(t.matches?(fact('foo' => [42])))
|
34
|
-
assert(!t.matches?(fact('foo' =>
|
34
|
+
assert(!t.matches?(fact('foo' => 'Hello!')))
|
35
35
|
assert(!t.matches?(fact('bar' => ['Hello!'])))
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_eq_matching
|
39
39
|
t = Factbase::Term.new(:eq, ['foo', 42])
|
40
|
+
assert(t.matches?(fact('foo' => 42)))
|
40
41
|
assert(t.matches?(fact('foo' => [10, 5, 6, -8, 'hey', 42, 9, 'fdsf'])))
|
41
42
|
assert(!t.matches?(fact('foo' => [100])))
|
43
|
+
assert(!t.matches?(fact('foo' => [])))
|
42
44
|
end
|
43
45
|
|
44
46
|
def test_lt_matching
|
@@ -61,7 +63,7 @@ class TestTerm < Minitest::Test
|
|
61
63
|
def test_not_exists_matching
|
62
64
|
t = Factbase::Term.new(:not, [Factbase::Term.new(:eq, ['foo', 100])])
|
63
65
|
assert(t.matches?(fact('foo' => [42, 12, -90])))
|
64
|
-
assert(!t.matches?(fact('foo' =>
|
66
|
+
assert(!t.matches?(fact('foo' => 100)))
|
65
67
|
end
|
66
68
|
|
67
69
|
def test_or_matching
|
data/test/test_factbase.rb
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
require 'minitest/autorun'
|
24
24
|
require 'json'
|
25
25
|
require 'nokogiri'
|
26
|
+
require 'yaml'
|
26
27
|
require_relative '../lib/factbase'
|
27
28
|
|
28
29
|
# Factbase main module test.
|
@@ -53,7 +54,7 @@ class TestFactbase < Minitest::Test
|
|
53
54
|
File.write(f.path, f1.export)
|
54
55
|
f2.import(File.read(f.path))
|
55
56
|
end
|
56
|
-
assert_equal(1, f2.query('(eq foo 42)').to_a.count)
|
57
|
+
assert_equal(1, f2.query('(eq foo 42)').extend(Enumerable).to_a.count)
|
57
58
|
end
|
58
59
|
|
59
60
|
def test_to_json
|
@@ -75,4 +76,17 @@ class TestFactbase < Minitest::Test
|
|
75
76
|
assert(!xml.xpath('/fb[count(f) = 2]').empty?)
|
76
77
|
assert(!xml.xpath('/fb/f/foo[v="42"]').empty?)
|
77
78
|
end
|
79
|
+
|
80
|
+
def test_to_yaml
|
81
|
+
fb = Factbase.new
|
82
|
+
f = fb.insert
|
83
|
+
f.foo = 42
|
84
|
+
f.foo = 256
|
85
|
+
fb.insert
|
86
|
+
yaml = YAML.load(fb.to_yaml)
|
87
|
+
assert_equal(2, yaml['facts'].size)
|
88
|
+
assert_equal(42, yaml['facts'][0]['foo'][0])
|
89
|
+
assert_equal(256, yaml['facts'][0]['foo'][1])
|
90
|
+
assert_equal(2, yaml['facts'][1]['id'])
|
91
|
+
end
|
78
92
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yaml
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.3'
|
41
55
|
description: Fact base in memory and on disc
|
42
56
|
email: yegor256@gmail.com
|
43
57
|
executables: []
|