factbase 0.0.42 → 0.0.44

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42066d9d82538ecb6f0ec8df6cc711f4328e1ba496f00366fe67719ca8a1185e
4
- data.tar.gz: d40e21b7e426af5184b9b03f515da4508b1e1e9e52995f566b16c778eefefca3
3
+ metadata.gz: 7942029d876a9fee77f167bb9e9d7311445e16fa38c9654dfd6eae231fb9c366
4
+ data.tar.gz: 102f08927aafc6900d4563e90cbabb9311166307e1ca57a9bd4e484ff8be684a
5
5
  SHA512:
6
- metadata.gz: ff04d1f7e3eb1b18b36544ea8fb61280cda250a5e9920ba7b858092ae7c13111efce537d39acd7119f2f70c8704a89d06c98bf54b5a4639b4f187599f61eecbc
7
- data.tar.gz: '09ba7d04f933f758c1db716c9490d464a2202644560a594bfae0a77e8bee8d26dcc38605101417a062ccd5c9645b5187e7f069e8f31e6bc782e48dc79775a347'
6
+ metadata.gz: d6877f4b3dbe627819256cda88214fd170e89e37521c2936daa0fed5a02b1450fc98157c53e92d2f38e48522dd617d901609ec1b23b96875abb68a7c231d5a47
7
+ data.tar.gz: 482f13ec05d51bf726049ed44627ec2719ee17b1a5b387eb7ebb6ee98a760523702f9f81540e6e10ff2dc211a90321742c5796cb63ef9ee4aa64fa6777886b81
@@ -53,11 +53,14 @@ class Factbase::Rules
53
53
  def txn(this = self, &)
54
54
  before = @check
55
55
  @check = Blind.new
56
- @fb.txn(this, &)
56
+ modified = @fb.txn(this, &)
57
57
  @check = before
58
- @fb.query('(always)').each do |f|
59
- @check.it(f)
58
+ if modified
59
+ @fb.query('(always)').each do |f|
60
+ @check.it(f)
61
+ end
60
62
  end
63
+ modified
61
64
  end
62
65
 
63
66
  def export
@@ -21,7 +21,6 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'json'
24
- require 'time'
25
24
  require_relative '../factbase'
26
25
 
27
26
  # Factbase to JSON converter.
@@ -37,14 +36,15 @@ require_relative '../factbase'
37
36
  # License:: MIT
38
37
  class Factbase::ToJSON
39
38
  # Constructor.
40
- def initialize(fb)
39
+ def initialize(fb, sorter = '_id')
41
40
  @fb = fb
41
+ @sorter = sorter
42
42
  end
43
43
 
44
44
  # Convert the entire factbase into JSON.
45
45
  # @return [String] The factbase in JSON format
46
46
  def json
47
47
  maps = Marshal.load(@fb.export)
48
- maps.map { |m| m.sort.to_h }.to_json
48
+ maps.sort_by { |m| m[@sorter] }.map { |m| m.sort.to_h }.to_json
49
49
  end
50
50
  end
@@ -37,8 +37,9 @@ require_relative '../factbase'
37
37
  # License:: MIT
38
38
  class Factbase::ToXML
39
39
  # Constructor.
40
- def initialize(fb)
40
+ def initialize(fb, sorter = '_id')
41
41
  @fb = fb
42
+ @sorter = sorter
42
43
  end
43
44
 
44
45
  # Convert the entire factbase into XML.
@@ -48,12 +49,11 @@ class Factbase::ToXML
48
49
  maps = Marshal.load(bytes)
49
50
  meta = {
50
51
  version: Factbase::VERSION,
51
- dob: Time.now.utc.iso8601,
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
- maps.each do |m|
56
+ maps.sort_by { |m| m[@sorter] }.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)
@@ -21,7 +21,6 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'yaml'
24
- require 'time'
25
24
  require_relative '../factbase'
26
25
 
27
26
  # Factbase to YAML converter.
@@ -37,14 +36,15 @@ require_relative '../factbase'
37
36
  # License:: MIT
38
37
  class Factbase::ToYAML
39
38
  # Constructor.
40
- def initialize(fb)
39
+ def initialize(fb, sorter = '_id')
41
40
  @fb = fb
41
+ @sorter = sorter
42
42
  end
43
43
 
44
44
  # Convert the entire factbase into YAML.
45
45
  # @return [String] The factbase in YAML format
46
46
  def yaml
47
47
  maps = Marshal.load(@fb.export)
48
- YAML.dump({ 'facts' => maps.map { |m| m.sort.to_h } })
48
+ YAML.dump({ 'facts' => maps.sort_by { |m| m[@sorter] }.map { |m| m.sort.to_h } })
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.42'
82
+ VERSION = '0.0.44'
83
83
 
84
84
  # An exception that may be thrown in a transaction, to roll it back.
85
85
  class Rollback < StandardError; end
@@ -159,22 +159,30 @@ class Factbase
159
159
  # inserted and all changes that happened in the block will be rolled back.
160
160
  #
161
161
  # @param [Factbase] this The factbase to use (don't provide this param)
162
+ # @return [Boolean] TRUE if some changes have been made, FALSE otherwise
162
163
  def txn(this = self)
163
164
  copy = this.dup
164
165
  begin
165
166
  yield copy
166
167
  rescue Factbase::Rollback
167
- return
168
+ return false
168
169
  end
170
+ modified = false
169
171
  @mutex.synchronize do
170
172
  after = Marshal.load(copy.export)
171
173
  after.each_with_index do |m, i|
172
- @maps << {} if i >= @maps.size
174
+ if i >= @maps.size
175
+ @maps << {}
176
+ modified = true
177
+ end
173
178
  m.each do |k, v|
179
+ next if @maps[i][k] == v
174
180
  @maps[i][k] = v
181
+ modified = true
175
182
  end
176
183
  end
177
184
  end
185
+ modified
178
186
  end
179
187
 
180
188
  # Export it into a chain of bytes.
@@ -22,6 +22,7 @@
22
22
 
23
23
  require 'minitest/autorun'
24
24
  require_relative '../../lib/factbase/term'
25
+ require_relative '../../lib/factbase/syntax'
25
26
 
26
27
  # Term test.
27
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -227,6 +228,27 @@ class TestTerm < Minitest::Test
227
228
  assert(msg.include?('at (at)'), msg)
228
229
  end
229
230
 
231
+ def test_aggregation
232
+ maps = [
233
+ { 'x' => 1, 'y' => 0, 'z' => 4 },
234
+ { 'x' => 2, 'y' => 42, 'z' => 3 },
235
+ { 'x' => 3, 'y' => 42, 'z' => 5 },
236
+ { 'x' => 4, 'y' => 42, 'z' => 2 },
237
+ { 'x' => 5, 'y' => 42, 'z' => 1 },
238
+ { 'x' => 8, 'y' => 0, 'z' => 6 }
239
+ ]
240
+ {
241
+ '(eq x (agg (eq y 42) (min x)))' => '(eq x 2)',
242
+ '(eq z (agg (eq y 0) (max z)))' => '(eq x 8)',
243
+ '(eq x (agg (and (eq y 42) (gt z 1)) (max x)))' => '(eq x 4)',
244
+ '(and (eq x (agg (eq y 42) (min x))) (eq z 3))' => '(eq x 2)'
245
+ }.each do |q, r|
246
+ t = Factbase::Syntax.new(q).to_term
247
+ f = maps.find { |m| t.evaluate(fact(m), maps) }
248
+ assert(Factbase::Syntax.new(r).to_term.evaluate(fact(f), []))
249
+ end
250
+ end
251
+
230
252
  private
231
253
 
232
254
  def fact(map = {})
@@ -56,7 +56,6 @@ class TestToXML < Minitest::Test
56
56
  fb.insert.x = 42
57
57
  to = Factbase::ToXML.new(fb)
58
58
  xml = Nokogiri::XML.parse(to.xml)
59
- assert(!xml.xpath('/fb[@dob]').empty?)
60
59
  assert(!xml.xpath('/fb[@version]').empty?)
61
60
  assert(!xml.xpath('/fb[@size]').empty?)
62
61
  end
@@ -33,9 +33,10 @@ class TestToYAML < Minitest::Test
33
33
  def test_simple_rendering
34
34
  fb = Factbase.new
35
35
  f = fb.insert
36
+ f._id = 1
36
37
  f.foo = 42
37
38
  f.foo = 256
38
- fb.insert
39
+ fb.insert._id = 2
39
40
  to = Factbase::ToYAML.new(fb)
40
41
  yaml = YAML.load(to.yaml)
41
42
  assert_equal(2, yaml['facts'].size)
@@ -143,10 +143,11 @@ class TestFactbase < Minitest::Test
143
143
 
144
144
  def test_txn_with_rollback
145
145
  fb = Factbase.new
146
- fb.txn do |fbt|
146
+ modified = fb.txn do |fbt|
147
147
  fbt.insert.bar = 33
148
148
  raise Factbase::Rollback
149
149
  end
150
+ assert(!modified)
150
151
  assert_equal(0, fb.query('(always)').each.to_a.size)
151
152
  end
152
153
  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.42
4
+ version: 0.0.44
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-04 00:00:00.000000000 Z
11
+ date: 2024-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json