Você sabe o que é um decorator?
Basicamente ele é utilizado para sobre escrever métodos antes que – de fato – o método original seja chamado! Vamos fazer um exemplo prático para entender melhor. Imagine o seguinte cenário:
Temos alguns endpoints que realizam operações de criação e update no banco de dados. Para cada um desses métodos, queremos salvar o dia da criação do registro e quem fez o cadastro, e o dia da alteração do registro e que fez o cadastro!
Usando MongoDB é muito fácil fazer isso, basta indicarmos no model um timestamp: true.
Exemplo:
var clienteSchema = new mongoose.Schema({
nome: {
type: String
}
}, {
timestamps: true
});
Qualquer inclusão ou alteração que ocorrer, o MongoDB incluirá os valores da data da criação e ou alteração! Mas no nosso caso, não estamos usando MongoDB e queremos incluir a pessoa que fez a ação!
Voltando ao nosso cenário, criamos o nosso Service que receberá os dados e enviará para API.
Eu vou fazer bem básico, pois a intenção aqui é focar no decorator!
Service.create = (data) => {
data.createdAt = firebase.database.ServerValue.TIMESTAMP; // ou new Date().getTime()
data.createdBy = firebase.auth().currentUser.displayName; // ou currentUser.uid;
return this._$firebaseArray(firebase.database.ref('suaRefencia')).$add(data)
}
Service.update = (id, data) => {
data.createdAt = firebase.database.ServerValue.TIMESTAMP; // ou new Date().getTime()
data.createdBy = firebase.auth().currentUser.displayName; // ou currentUser.uid;
return this._$firebaseObject(firebase.database.ref('suaRefencia').child(id)).$save(data)
}
Olha que chato: se toda vez que a gente criar um serviço tivermos que ficar colocando esse código, createdAt, createdBy, updatedAt, updatedBy, etc. O ideal é quando a gente chamar o $add ou $save – antes de executar o método – que ele inclua essas propriedades no nosso objeto data. É aí que entra o decorator!
let app = angular.module('app', []);
app.config(function($provide) {
$provide.decorator('$firebaseArray', function($delegate, $window) {
var _add = $delegate.prototype.$add;
$delegate.prototype.$add = function(newData) {
newData['createdAt'] = $window.firebase.database.ServerValue.TIMESTAMP;
newData['createdBy'] = $window.firebase.auth().currentUser.displayName; //uid
return _add.call(this, newData);
};
return $delegate;
});
})
app.config(function($provide) {
$provide.decorator('$firebaseObject', function($delegate, $window) {
var _save = $delegate.prototype.$save;
$delegate.prototype.$save = function() {
this['updatedAt'] = $window.firebase.database.ServerValue.TIMESTAMP;
this['updatedBy'] = $window.firebase.auth().currentUser.displayName;
return _save.call(this);
};
return $delegate;
});
})
Agora no nosso controller fazemos a chamada do Service:
let data = {
nome: 'Joao da Silva';
idade: 33
}
Service.create(data);
Nosso service chama o firebaseArray, mas antes entra no decorator, que insere a data da criação e o nome do usuário logado no Firebase! E assim, a gente finaliza nossa tarefa.
Espero que ajude!



