rndb 0.1.1 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c745160e3fa8b2713e1661bc83157c29746e9ed7125b6ac332700d81a3db7a7f
4
- data.tar.gz: 52b92a38e619572b13ec8e5b50dac552d1561832fe39f858b9ce269db6eaadb7
3
+ metadata.gz: 214e9ee89f6ee4b994baf74bea9a34f49fc89e09c99ce436960ceb2c92d3d670
4
+ data.tar.gz: 85840a5d5346fb2334d395fa820d5f6111e43df485cd0b3e6a636a80f1837c61
5
5
  SHA512:
6
- metadata.gz: f6930929cdf9a3958de8ae0c730bc619c74b62fe145776fd53a6a61fc84e7b1dcf7af0752955f47bac3d9e601a1907aa2d36fca6774bd765c87ad7668f07d01a
7
- data.tar.gz: d9cf1aee0b156bb6e0d02491b89a3cb4abb4ca9bca1e55d99751d0ec3375aef75a7490da48d3cd78a7860c3879d52ce4b170ea33fd7ecbadd7f5f9786380ebf6
6
+ metadata.gz: bf56a0511606581fff82c10d25573c826daab12823cd02bf2e003f8abfb9912d8a58a641dfca3d8e1f611e6a307762a6ee4adb5df26f2ab44011521904cdf3e7
7
+ data.tar.gz: 8f63e7aa951fdf2b304985686bfd8f6ccc8ed5bfd672cddf4634e75e3efbd6e4446ff6942d28e270289357efbc95ff5aee1244fdae8dba2d93fcbde4e3835455
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![test](https://github.com/kranzky/rndb/actions/workflows/test.yml/badge.svg)](https://github.com/kranzky/rndb/actions/workflows/test.yml)
2
2
  [![Coverage Status](https://coveralls.io/repos/github/kranzky/rndb/badge.svg?branch=main)](https://coveralls.io/github/kranzky/rndb?branch=main)
3
+ [![Gem Version](https://badge.fury.io/rb/rndb.svg)](https://badge.fury.io/rb/rndb)
3
4
 
4
5
  # RnDB
5
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/lib/rndb/query.rb CHANGED
@@ -19,6 +19,11 @@ module RnDB
19
19
  @table[@ids[index]]
20
20
  end
21
21
 
22
+ # Retrieve the index of the specified ID.
23
+ def index(id)
24
+ @ids.index(id)
25
+ end
26
+
22
27
  # Implemented to be consistent with #first, which we get by magic.
23
28
  def last
24
29
  self[-1] unless count.zero?
data/lib/rndb/table.rb CHANGED
@@ -31,17 +31,35 @@ module RnDB
31
31
  private
32
32
 
33
33
  def _generate_all
34
- _schema[:columns].each_key do |name|
34
+ _schema[:columns].each do |name, column|
35
+ _generate_column_key(name) if column[:generator] && column[:distribution]
35
36
  _generate_column(name)
36
37
  end
38
+ _schema[:associations].each_key do |name|
39
+ _generate_association_id(name)
40
+ end
37
41
  @_attributes
38
42
  end
39
43
 
44
+ def _generate_column_key(name)
45
+ @_attributes ||= { id: @id }
46
+ @_attributes["#{name}_key".to_sym] ||= self.class.key(@id, name)
47
+ end
48
+
40
49
  def _generate_column(name)
41
50
  @_attributes ||= { id: @id }
42
51
  @_attributes[name] ||= self.class.value(@id, name)
43
52
  end
44
53
 
54
+ def _generate_association_id(name)
55
+ @_attributes ||= { id: @id }
56
+ @_attributes["#{name}_id".to_sym] ||= _generate_association(name)&.id
57
+ end
58
+
59
+ def _generate_association(name)
60
+ self.class.join(@id, name)
61
+ end
62
+
45
63
  def _validate!
46
64
  self.class.send(:_validate!)
47
65
  end
@@ -67,15 +85,7 @@ module RnDB
67
85
  # Return a Query that matches the supplied constraints
68
86
  def where(constraints={})
69
87
  _validate!
70
- ids = Thicket.new(0..._schema[:size])
71
- constraints.each do |attribute, values|
72
- column = _schema[:columns][attribute]
73
- other = Array(values).reduce(Thicket.new) do |thicket, value|
74
- thicket | column[:mapping][value]
75
- end
76
- ids &= other
77
- end
78
- Query.new(self, ids)
88
+ Query.new(self, _query(constraints, _schema[:size]))
79
89
  end
80
90
 
81
91
  # Return all records.
@@ -110,41 +120,67 @@ module RnDB
110
120
 
111
121
  # Add a new column to the Table model.
112
122
  def column(attribute, *args)
123
+ column = _schema[:columns][attribute]
113
124
  args.each do |arg|
114
125
  index =
115
126
  case arg
116
- when Hash
127
+ when Hash, Array
117
128
  :distribution
118
129
  when Proc
119
130
  :generator
120
131
  else
121
132
  raise "unsupported column parameter"
122
133
  end
123
- _schema[:columns][attribute][index] = arg
134
+ column[index] = arg
135
+ end
136
+ if column[:generator] && column[:distribution]
137
+ define_method("#{attribute}_key") do
138
+ _generate_column_key(attribute)
139
+ end
124
140
  end
125
141
  define_method(attribute) do
126
142
  _generate_column(attribute)
127
143
  end
128
144
  end
129
145
 
146
+ # Add an association between two Table models.
147
+ def association(attribute, *args)
148
+ args.each do |arg|
149
+ _schema[:associations][attribute] = arg
150
+ end
151
+ define_method("#{attribute}_id".to_sym) do
152
+ _generate_association_id(attribute)
153
+ end
154
+ define_method(attribute) do
155
+ _generate_association(attribute)
156
+ end
157
+ end
158
+
130
159
  # Generate a random number, intended to be used in lambdas. The number
131
160
  # will have been seeded appropriately to ensure determinism.
132
- def rand(args)
161
+ def rand(*args)
133
162
  _validate!
134
- _db.prng.rand(args)
163
+ _db.prng.rand(*args)
164
+ end
165
+
166
+ # Retrieve the key that can be queried on for generated attributes.
167
+ def key(id, attribute)
168
+ @current = id
169
+ _validate!
170
+ column = _schema[:columns][attribute]
171
+ return if column[:distribution].nil?
172
+ column[:mapping].find do |_, ids|
173
+ ids.include?(id)
174
+ end&.first
135
175
  end
136
176
 
137
177
  # Retrieve the value of the given attribute for the given ID.
138
178
  def value(id, attribute)
179
+ @current = id
139
180
  _validate!
140
181
  return id if attribute == :id
141
182
  column = _schema[:columns][attribute]
142
- value =
143
- unless column[:distribution].nil?
144
- column[:mapping].find do |_, ids|
145
- ids.include?(id)
146
- end&.first
147
- end
183
+ value = key(id, attribute)
148
184
  unless column[:generator].nil?
149
185
  _seed_prng(id, attribute)
150
186
  value =
@@ -157,6 +193,27 @@ module RnDB
157
193
  value
158
194
  end
159
195
 
196
+ # Return the instance joined to the current ID.
197
+ def join(id, name)
198
+ @current = id
199
+ _schema[:associations][name].each do |context|
200
+ next unless (index = where(context[:where]).index(id))
201
+ return where(context[:joins])[index]
202
+ end
203
+ nil
204
+ end
205
+
206
+ def get(attribute)
207
+ raise unless @current
208
+ if _schema[:columns].key?(attribute)
209
+ value(@current, attribute)
210
+ elsif _schema[:associations].key?(attribute)
211
+ join(@current, attribute)
212
+ else
213
+ raise "no such attribute"
214
+ end
215
+ end
216
+
160
217
  private
161
218
 
162
219
  def _db
@@ -174,24 +231,52 @@ module RnDB
174
231
  mapping: {},
175
232
  generator: nil
176
233
  }
234
+ end,
235
+ associations: Hash.new do |associations, key|
236
+ associations[key] = nil
177
237
  end
178
238
  }
179
239
  end
180
240
  Thread.current[:rndb_tables][table_name]
181
241
  end
182
242
 
243
+ def _query(constraints, size)
244
+ ids = Thicket.new(0...size)
245
+ constraints.each do |attribute, values|
246
+ column = _schema[:columns][attribute]
247
+ raise "no mapping for column" if column[:mapping].empty?
248
+ other = Array(values).reduce(Thicket.new) do |thicket, value|
249
+ thicket | column[:mapping][value]
250
+ end
251
+ ids &= other
252
+ end
253
+ ids
254
+ end
255
+
256
+ def _migrate_column(column, ids, distribution)
257
+ min = 0.0
258
+ distribution.each do |value, probability|
259
+ max = min + probability
260
+ column[:mapping][value] ||= Thicket.new
261
+ column[:mapping][value] |= ids * (min..max)
262
+ min = max
263
+ end
264
+ end
265
+
183
266
  def _migrate(size)
184
267
  raise "table already migrated" unless _schema[:class].nil?
185
268
  ids = Thicket.new(0...size)
186
269
  _schema[:columns].each_value do |column|
187
270
  distribution = column[:distribution]
188
271
  next if distribution.nil?
189
- raise "distribution must sum to unity" unless distribution.values.sum == 1
190
- min = 0.0
191
- column[:distribution].each do |value, probability|
192
- max = min + probability
193
- column[:mapping][value] = ids * (min..max)
194
- min = max
272
+ if distribution.is_a?(Array)
273
+ distribution.each do |context|
274
+ thicket = ids & _query(context[:where], size)
275
+ _migrate_column(column, thicket, context[:stats])
276
+ end
277
+ else
278
+ raise "distribution must sum to unity" unless distribution.values.sum == 1
279
+ _migrate_column(column, ids, distribution)
195
280
  end
196
281
  ids =
197
282
  column[:mapping].values.reduce(Thicket.new) do |thicket, other|
data/rndb.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: rndb 0.1.1 ruby lib
5
+ # stub: rndb 0.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "rndb".freeze
9
- s.version = "0.1.1"
9
+ s.version = "0.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Lloyd Kranzky".freeze]
14
- s.date = "2021-02-25"
14
+ s.date = "2021-02-26"
15
15
  s.description = "".freeze
16
16
  s.email = "lloyd@kranzky.com".freeze
17
17
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rndb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lloyd Kranzky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-25 00:00:00.000000000 Z
11
+ date: 2021-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc