namo 0.31.4 → 0.31.5
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/CHANGELOG +12 -0
- data/README.md +2 -0
- data/lib/Namo/Collection.rb +13 -2
- data/lib/Namo/VERSION.rb +1 -1
- data/test/Namo/Collection_test.rb +42 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 77e56d154536ec5ebde8dbb2d660277007a76d4ec108c6b669ff96399f9991d7
|
|
4
|
+
data.tar.gz: 79baaf53cfd3417b5db049b7c2ea6701c60580e97f41235bcafb91538c49d427
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ffa93bb4ad5f35eaffcefa76778dbffc843bc24a95130327d4da88e8ae8e3103fdc6a28a2eabaf0f38b996b768e6125f7e1538612ac8c922e0bb7c495870f128
|
|
7
|
+
data.tar.gz: 24e8d924c61152922e757ab30b87662cede03e6dcb85dbb2cd964de4b9230ee4d65617e74760b7e37a3d8831dd332c3f46e829adfbaa82cf275f2a9108528558
|
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 20260826
|
|
4
|
+
|
|
5
|
+
0.31.5: ~ Namo::Collection#detail, #as_detail: the detail view carries the members' formulae.
|
|
6
|
+
|
|
7
|
+
1. ~ Namo::Collection#detail: the returned Namo carries the members' formulae, folded in member order so that a later member wins a name collision, as a later member wins a collision of names in <<. It had been built with none, so the view documented at 0.18.0 as the lossless union of the members' rows dropped every derived dimension: group_by hands each member the source's formulae, and detail handed them back stripped.
|
|
8
|
+
2. ~ Namo::Collection#as_detail: merges the detail view's formulae into the Collection's own, the Collection having become that view. Without it the round trip still lost them, as_detail having taken only the data.
|
|
9
|
+
3. ~ script/demo: the collections section checks the round trip with === rather than ==, == comparing row multisets alone and so unable to see the formulae go missing, which is why this stood.
|
|
10
|
+
4. ~ README.md: the four views, on which of them carries formulae and why.
|
|
11
|
+
5. ~ ROADMAP.md: + 0.31.5.
|
|
12
|
+
6. ~ Namo::VERSION: /0.31.4/0.31.5/
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
## 20260826
|
|
4
16
|
|
|
5
17
|
0.31.4: ~ Namo::Collection#inspect: the members are rendered, nested under their names.
|
data/README.md
CHANGED
|
@@ -1121,6 +1121,8 @@ Detail is the lazy view because a Collection's rows simply *are* its members' ro
|
|
|
1121
1121
|
|
|
1122
1122
|
#### Four view methods
|
|
1123
1123
|
|
|
1124
|
+
`detail` carries the members' formulae, its rows being the members' rows — folded in member order, so a later member wins a name collision as it wins a collision of names in `<<`. A `summary`'s rows are reductions, holding neither the dimensions those formulae read nor the rows they read them from, so it carries none.
|
|
1125
|
+
|
|
1124
1126
|
The views come in a non-mutating pair and a mutating pair:
|
|
1125
1127
|
|
|
1126
1128
|
- `summary(dimension = nil, by:, reducer:, &block)` and `detail(by:)` are **non-mutating** — each returns a fresh `Namo` derived from the members, leaving the Collection untouched. Use these when you want a view to keep: assign the result to a variable and operate on it independently.
|
data/lib/Namo/Collection.rb
CHANGED
|
@@ -42,7 +42,7 @@ class Namo
|
|
|
42
42
|
member.data.map{|row| row.key?(by) ? row : row.merge(by => member.name)}
|
|
43
43
|
end
|
|
44
44
|
)
|
|
45
|
-
Namo.new(rows)
|
|
45
|
+
Namo.new(rows, formulae: member_formulae)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def as_summary(dimension = nil, by: :member, reducer: :sum, &block)
|
|
@@ -52,7 +52,9 @@ class Namo
|
|
|
52
52
|
|
|
53
53
|
def as_detail(positional_by = nil, by: :member)
|
|
54
54
|
by = positional_by || by
|
|
55
|
-
|
|
55
|
+
view = detail(by)
|
|
56
|
+
@data = view.data
|
|
57
|
+
@formulae = @formulae.merge(view.formulae)
|
|
56
58
|
self
|
|
57
59
|
end
|
|
58
60
|
|
|
@@ -70,6 +72,15 @@ class Namo
|
|
|
70
72
|
|
|
71
73
|
private
|
|
72
74
|
|
|
75
|
+
# The members' formulae, folded in member order so that a later member wins a
|
|
76
|
+
# name collision, as a later member wins a collision of names in <<. The
|
|
77
|
+
# detail view is the members' rows, so it must be able to answer what the
|
|
78
|
+
# members can answer of them; group_by hands every member the same formulae,
|
|
79
|
+
# so only an assembled Collection can have members which disagree.
|
|
80
|
+
def member_formulae
|
|
81
|
+
@members.map(&:formulae).reduce(Formulae.new){|merged, formulae| merged.merge(formulae)}
|
|
82
|
+
end
|
|
83
|
+
|
|
73
84
|
def inspected_members
|
|
74
85
|
return '[]' if @members.empty?
|
|
75
86
|
shown = [@members.length, INSPECTED_ROWS].min
|
data/lib/Namo/VERSION.rb
CHANGED
|
@@ -347,6 +347,48 @@ describe Namo::Collection do
|
|
|
347
347
|
end
|
|
348
348
|
end
|
|
349
349
|
|
|
350
|
+
describe "the detail view and its formulae" do
|
|
351
|
+
def readings
|
|
352
|
+
namo = Namo.new([
|
|
353
|
+
{station: "Melbourne", month: "2025-01", high_temp: 26.4, mean_temp: 25.9},
|
|
354
|
+
{station: "Perth", month: "2025-01", high_temp: 32.0, mean_temp: 30.0}])
|
|
355
|
+
namo[:anomaly] = proc{|row| (row[:high_temp] - row[:mean_temp]).round(1)}
|
|
356
|
+
namo
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "carries the members' formulae, the view being the members' rows" do
|
|
360
|
+
_(readings.group_by(:station).detail(:station).derived_dimensions).must_equal [:anomaly]
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
it "answers a derived dimension through the detail view" do
|
|
364
|
+
_(readings.group_by(:station).detail(:station).values(:anomaly)).must_equal [0.5, 2.0]
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# == compares row multisets and cannot see a formula go missing, so it called
|
|
368
|
+
# the partition exact while the derived dimensions were being dropped. === is
|
|
369
|
+
# the operator which compares the formula names too.
|
|
370
|
+
it "inverts the partition exactly, formulae and all" do
|
|
371
|
+
source = readings
|
|
372
|
+
_(source.group_by(:station).as_detail(:station)).must_be :===, source
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "folds the members' formulae, a later member winning the name" do
|
|
376
|
+
first = Namo.new([{a: 1}], name: :first)
|
|
377
|
+
first[:b] = proc{|row| :from_first}
|
|
378
|
+
second = Namo.new([{a: 2}], name: :second)
|
|
379
|
+
second[:b] = proc{|row| :from_second}
|
|
380
|
+
collection = Namo::Collection.new
|
|
381
|
+
collection << first << second
|
|
382
|
+
_(collection.detail.values(:b)).must_equal [:from_second, :from_second]
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# A summary's rows are reductions, holding neither the dimensions the members'
|
|
386
|
+
# formulae read nor the rows they read them from, so it carries none.
|
|
387
|
+
it "leaves the summary without them" do
|
|
388
|
+
_(readings.group_by(:station).summary(:high_temp).derived_dimensions).must_equal []
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
350
392
|
describe "#inspect" do
|
|
351
393
|
def collection_of(members, rows_each)
|
|
352
394
|
rows = (1..members).flat_map{|member| (1..rows_each).map{|row| {group: "g#{member}", n: row}}}
|