Answer product-owner round 2: render a record column a name binds whole from the pick
This commit is contained in:
@@ -137,8 +137,8 @@ it as nothing.
|
|||||||
A record is one render, so its columns read one pick of each [name](#names) its category
|
A record is one render, so its columns read one pick of each [name](#names) its category
|
||||||
binds: `"code": "{/currency as c}{c.code}"` beside `"symbol": "{c.symbol}"` is one
|
binds: `"code": "{/currency as c}{c.code}"` beside `"symbol": "{c.symbol}"` is one
|
||||||
currency, while `{/currency.code}` and `{/currency.symbol}` in two columns may name two. A
|
currency, while `{/currency.code}` and `{/currency.symbol}` in two columns may name two. A
|
||||||
field a name binds draws afresh as a column of its own, so write the column through the name,
|
field the format binds whole, `{place as p}`, is a column holding that pick, so it agrees with
|
||||||
`"where": "{p}"` beside `{place as p}`, for it to agree with the columns reading `p`.
|
the columns reading `p`.
|
||||||
|
|
||||||
A category never references itself: `{/users.first}` or a bare `{/users}` inside `users`
|
A category never references itself: `{/users.first}` or a bare `{/users}` inside `users`
|
||||||
describes a draw other than the fields beside it. Read a sibling as a field, and put a
|
describes a draw other than the fields beside it. Read a sibling as a field, and put a
|
||||||
|
|||||||
@@ -285,3 +285,25 @@ func TestASubFieldIsReachableByFake(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAFieldBoundWholeIsItsPickAsAColumn(t *testing.T) {
|
||||||
|
f := newGenerator(t, writeData(t, map[string]string{
|
||||||
|
"row": `{"format":"{place as p}{p.locality}","place":[{"format":"{locality}","locality":"Stockholm","zip":"1"},{"format":"{locality}","locality":"Tranås","zip":"5"}],"zip":"{p.zip}"}`,
|
||||||
|
}), WithSeed(1))
|
||||||
|
zips := map[string]string{"Stockholm": "1", "Tranås": "5"}
|
||||||
|
seen := map[string]bool{}
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
r, err := f.FakeRecord("row")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c := r.Columns()
|
||||||
|
if zips[c[0].Value] != c[1].Value {
|
||||||
|
t.Fatalf("%s: want the place column and the zip read through p one place", r.JSON())
|
||||||
|
}
|
||||||
|
seen[c[0].Value] = true
|
||||||
|
}
|
||||||
|
if len(seen) != 2 {
|
||||||
|
t.Errorf("place drew only %v in 100 records, want both", seen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -266,8 +266,28 @@ func renderRecord(s *generatorState, t *template, columns []Column, sc renderSco
|
|||||||
}
|
}
|
||||||
r := &Record{columns: append([]Column(nil), columns...)}
|
r := &Record{columns: append([]Column(nil), columns...)}
|
||||||
for i := range r.columns {
|
for i := range r.columns {
|
||||||
column := renderLeaf(s, t.fields[r.columns[i].Name], sc)
|
field := t.fields[r.columns[i].Name]
|
||||||
|
var column readValue
|
||||||
|
if b := bindingOfWhole(t, field); b != nil {
|
||||||
|
column = readName(s, sc, arm{kind: namedRead, named: b, levels: []string{""}})
|
||||||
|
} else {
|
||||||
|
column = renderLeaf(s, field, sc)
|
||||||
|
}
|
||||||
r.columns[i].Value, r.columns[i].Null = column.text, column.null
|
r.columns[i].Value, r.columns[i].Null = column.text, column.null
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bindingOfWhole is the name t binds to the whole of field, whose pick the field's column renders
|
||||||
|
// so the row agrees with the columns reading the name; nil where none does.
|
||||||
|
func bindingOfWhole(t *template, field node) *nameBinding {
|
||||||
|
if t.ownNameScope == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, b := range t.ownNameScope.order {
|
||||||
|
if b.bindsField() && b.binder == t && len(b.tail) == 0 && b.head == field {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user