# Бизнес правила като текст с NEWMACRO()

> Компилирайте малки правила, написани на прост език (IF, ELSE, AND, OR, RETURN, извиквания на помощници), във функция, която изпълнявате с модел, така че правилата да могат да живеят във файл или в база данни.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: bg
Content-SHA256: be3526c31669b94e45e579f5c564447b727a2219f5189c85d208e9aa059d45b4
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`NEWMACRO(text, [nocompile], [isasync])` превръща няколко реда от малък език във функция `function(model, helpers)`. Предназначен е за правила, които се променят по-често от кода: отстъпка, цена, проверка на права, валидация, която някой, който не пише JavaScript, поддържа във файл или в база данни.

Езикът, както беше проверен:

- `IF condition`, `ELSE IF condition`, `ELSE` и `FI` (краят на условието) работят като в текстово правило. Условията използват `>`, `<`, `>=`, `<=`, `=` и `AND` / `OR`.
- `RETURN value` завършва макроса със стойност. `YES` и `NO` (също `TRUE`, `FALSE`, `OK`) са булеви стойности, текстът в кавички е текст, а числата са числа.
- Думата е **свойство на модела**, написано с малки букви: `age` чете `model.age`, а `total = price * qty` записва `model.total`.
- `NAME(arguments)` извиква **помощник**, функцията с това име (с малки букви) в обекта `helpers`, който подавате; вътре в нея `this` е моделът. С `isasync` на `true` макросът е async функция и изчаква помощниците.
- `#name` е временна променлива на изпълнението: `#temp = num + 1` и `RETURN #temp`.
- Използвайте имена от **няколко букви**: свойство или променлива от една буква не беше разпозната при проверките.

`NEWMACRO()` компилира текста с `new Function`, така че макросът е код: компилирайте само текст, който сте написали вие или който поддържа доверен човек, никога текст, изпратен от посетител. С `nocompile` на `true` връща JavaScript, който генерира, вместо функцията, което е полезно, за да видите какво прави едно правило.

```js controllers/rules.js
const helpers = {
	percent: function(value, rate) {
		return value * rate / 100;
	}
};

const age = NEWMACRO("IF age >= 18\n\tRETURN 'adult'\nELSE\n\tRETURN 'minor'\nFI");

const level = NEWMACRO("IF points > 100\n\tRETURN 'gold'\nELSE IF points > 50\n\tRETURN 'silver'\nELSE\n\tRETURN 'bronze'\nFI");

const access = NEWMACRO("IF active AND score >= 5\n\tRETURN yes\nFI\nRETURN no");

const total = NEWMACRO("total = price * qty\nIF qty >= 10\n\ttotal = total - PERCENT(total, 10)\nFI\nRETURN total");

const temporary = NEWMACRO("#next = count + 1\nRETURN #next");

const slow = NEWMACRO("RETURN LOOKUP(code)", false, true);

exports.install = function() {
	ROUTE('POST /rules/', rules);
	ROUTE('GET /source/', source);
};

async function rules($) {
	const model = $.body;
	$.json({
		age: age(model, helpers),
		level: level(model, helpers),
		access: access(model, helpers),
		total: total(model, helpers),
		model_total: model.total,
		temporary: temporary(model, helpers),
		slow: await slow(model, { lookup: async code => 'found ' + code })
	});
}

function source($) {
	$.plain(NEWMACRO("IF points > 100\n\tRETURN 'gold'\nFI", true));
}
```
