この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
渡辺です。 テストデータのメンテは大変なんです。
お題
こんな定義があったとします。
const locations = {
ENTRANCE: [100, 110],
EXIT: [500, 510]
};
これを踏まえて、YAMLでこんなデータを定義したいです。
- person_id: 101
x: 100 # ENTRANCE[0]
y: 110 # ENTRANCE[1]
- person_id: 102
x: 110 # ENTRANCE[0] + 10
y: 120 # ENTRANCE[1] + 10
- person_id: 103
x: 500 # EXIT[0]
y: 510 # EXIT[1]
locations
は変わる可能性があるので、変わったときに再計算すると辛いんです。
YAMLに式が書きたいんです。
解決方法を考えてみましょう。 YAMLはフォーマットを少しいじっても構いませんが、YAMLとして読み込める(valid)であることは条件です。
.
.
.
.
.
解答例
こうやってみました。
- person_id: 101
x: <ENTRANCE[0]>
y: <ENTRANCE[1]>
- person_id: 102
x: <ENTRANCE[0] + 10>
y: <ENTRANCE[1] + 10>
- person_id: 103
x: <EXIT[0]>
y: <EXIT[1]>
const fs = require('fs');
const YAML = require('yaml');
const locations = {
ENTRANCE: [100, 110],
EXIT: [500, 510]
};
let data = YAML.parse(fs.readFileSync(`./data.yaml`, 'utf8'));
const LOC = Object.keys(locations)
.map(key => (`let ${key}=${JSON.stringify(locations[key])}`))
.join(';');
const conv = (data) => {
const _conv = (obj) => {
Object.keys(obj).forEach(key => {
if (/^<.+>$/.test(obj[key])) {
let value = obj[key].substring(1, obj[key].length - 1);
obj[key] = eval(`${LOC};${value}`);
} else if (typeof obj[key] === 'object') {
_conv(obj[key]);
}
});
};
Object.keys(data).forEach(key => _conv(data[key]));
return data;
};
console.log(JSON.stringify(locations, null, 2));
console.log(JSON.stringify(data, null, 2));
console.log('----');
console.log(JSON.stringify(conv(data), null, 2));
実行結果
{
"ENTRANCE": [
100,
110
],
"EXIT": [
500,
510
]
}
[
{
"person_id": 101,
"x": "<ENTRANCE[0]>",
"y": "<ENTRANCE[1]>"
},
{
"person_id": 102,
"x": "<ENTRANCE[0] + 10>",
"y": "<ENTRANCE[1] + 10>"
},
{
"person_id": 103,
"x": "<EXIT[0]>",
"y": "<EXIT[1]>"
}
]
----
[
{
"person_id": 101,
"x": 100,
"y": 110
},
{
"person_id": 102,
"x": 110,
"y": 120
},
{
"person_id": 103,
"x": 500,
"y": 510
}
]
解説
式かどうか解るように <>
で囲みました。
式部分を評価する時に、 eval
を利用します。
この式の中で使う変数は、 locations
から作成します。
LOC
はゴニョゴニョ変換して、こんな感じ。
let ENTRANCE=[100,110];let EXIT=[500,510]
なので、
> eval('let ENTRANCE=[100,110];let EXIT=[500,510];ENTRANCE[0] + 10')
110
他になにか解決方法ないですかね?