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!