ember-compose-methods
v0.0.1
Published
Compose methods to make the code more functional.
Downloads
2
Maintainers
Readme
ember-compose-methods
Methods to make the code more functional and easy to handle.
Installation
ember install ember-compose-methods
Compose Method
compose
make a pipeline to execute functions in sequence and return a promise resolving the result.
Usage
Pass the functions to compose
in reverse sequence of execution, just to keep the same code visual sequence. If your sequence is fc3(fc2(fc1(...)))
it has to be compose(fc3, fc2, fc1)
.
/* controllers/application.js */
import Ember from 'ember';
import compose from 'ember-compose-methods/utils/compose';
export default Ember.Controller.extend({
value: undefined,
inputValue: undefined,
outputValue: undefined,
actions: {
calculate(value) {
let input = parseFloat(value);
Ember.set(this, 'inputValue', input);
const fc1 = x => x + 1;
const fc2 = x => x * 2;
const fc3 = x => x - 3;
const c = compose(fc3, fc2, fc1);
c(input).then(r => Ember.set(this, 'outputValue', r));
},
},
});
{{!-- templates/application.hbs --}}
Enter a number:
{{input type="number" value=value}}
<button {{action 'calculate' value}}>Calculate</button>
<br>Input: {{inputValue}}
<br>Output: {{outputValue}}
Result
Promises
It's possible to mix functions returning values or promises.compose
waits a promise resolve to fire the next function.
/* controllers/application.js */
import Ember from 'ember';
import compose from 'ember-compose-methods/utils/compose';
export default Ember.Controller.extend({
value: undefined,
inputValue: undefined,
outputValue: undefined,
actions: {
calculate(value) {
let input = parseFloat(value);
Ember.set(this, 'inputValue', input);
const fc1 = x => x + 1;
const fc2 = x => Promise.resolve(x * 2);
const fc3 = x => x - 3;
const c = compose(fc3, fc2, fc1);
c(input).then(r => Ember.set(this, 'outputValue', r));
},
},
});
Result
Functions in Objects
Sometimes the function is inside a object. Let's say you have some products models and want to sum the total. The attribute sumToTotal
is responsible for that, so use it as the first param on compose
method.
/* models/product.js */
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
price: DS.attr('number'),
discount: DS.attr('number'),
taxes: DS.attr('number'),
getDiscount: discount => 1 - (discount / 100),
getTaxes: taxes => (taxes / 100) + 1,
getPrice: (price, discount, taxes) => price * discount * taxes,
sumToTotal(subtotal = 0) {
const price = Ember.get(this, 'price')
, discount = this.getDiscount(Ember.get(this, 'discount'))
, taxes = this.getTaxes(Ember.get(this, 'taxes'))
, total = this.getPrice(price, discount, taxes);
return subtotal + total;
},
});
/* controllers/application.js */
import Ember from 'ember';
import compose from 'ember-compose-methods/utils/compose';
export default Ember.Controller.extend({
init() {
this._super(...arguments);
this.store.createRecord('product', {
name: 'Product 1',
price: 100,
discount: 10,
taxes: 0
}); //total = 90
this.store.createRecord('product', {
name: 'Product 2',
price: 50,
discount: 5,
taxes: 10
}); //total = 52,25
this.store.createRecord('product', {
name: 'Product 3',
price: 150,
discount: 15,
taxes: 30
}); //total = 165,75
const products = this.store.peekAll('product').toArray();
const c = compose('sumToTotal', ...products);
c().then(r => console.log('Total: ', r));
},
});
Result
> Total: 308
//0 + 90 = 90 + 52,25 = 142,25 + 165,75 = 308
Values, Promises and Objects
You can mix all of them!
/* controllers/application.js */
import Ember from 'ember';
import compose from 'ember-compose-methods/utils/compose';
export default Ember.Controller.extend({
value: undefined,
inputValue: undefined,
outputValue: undefined,
actions: {
calculate(value) {
let input = parseFloat(value);
Ember.set(this, 'inputValue', input);
const fc1 = x => x + 1;
const fc2 = {'calculate': x => x * 2};
const fc3 = {'calculate': x => Promise.resolve(x - 3)};
const c = compose('calculate', fc3, fc2, fc1);
c(input).then(r => Ember.set(this, 'outputValue', r));
},
},
});
Result