Ionic Framework, PouchDB y Cloudant: la combinación perfecta totalmente expuesta Parte 06


Esta es una continuación de la serie sobre desarrollo en móviles que comencé aquí. Les recomiendo comenzar a escribir el código fuente desde la parte 1 ya que no se publica el código para descarga.

El día de hoy un lector me hizo saber un error en mi código y pude darme cuenta que hay algo que no he explicado y es muy importante para cuando nuestra aplicación se hace cada vez mas grande. Más que con javascript, lo que hay que aclarar es con el modelo MVC.

MVC-web-application-development

Este es el gráfico mas conocido del modelo MVC, pero creo que podríamos fijarnos también en este otro:

ocEWx

La idea principal es que la Vista es manipulada solamente por el Controlador, mientras que el Controlador es el único que manipula el Modelo.

En el código que hemos hecho hasta ahora, el Controlador tiene referencias a los Servicios que representan al Modelo. Revisemos el archivo controllers.js

angular.module('controllers',['services'])
.controller('newsController',function($scope,db){
    db.init();
    $scope.notas=[];
    $scope.$on('refrescar',function(event,news){
       $scope.$apply(function(){
            $scope.notas = news;
       }) 
    })
})
.controller('detailController',function($scope,db,detail){
 db.get(detail).then(function(doc){
 $scope.event=doc;
 })
})

Podemos ver que en la definición de cada controlador hemos ingresado unas referencias a cada controlador. Para el controlador “newsController” se tiene $scope y db, donde $scope es un objeto Angular para intercambiar datos con la vista, y db es el servicio que hemos escrito en el archivo services.js. Por lo tanto si tenemos algún problema con el objeto db, donde debemos ir a revisar es en la definición del objeto db, así que si revisamos el archivo services.js.

angular.module('services',[])
.factory('db',function($rootScope){
        var key = 'XXXXXXXXXXXXXXX';
	var pass = 'XXXXXXXXXXXXXXX';
	var remote = 'https://'+key+':'+pass+'@servidor.cloudant.com/news';
	var db;
	var mostrar = function(){
        db.allDocs({startkey:'news_\uffff',endkey:'news_',descending: true,include_docs:true})
                    .then(function(result){
                    $rootScope.$broadcast('refrescar',result.rows);
                });
    };
    return {
        init: function(){
            if (!db) {
                db = new PouchDB('news');
            };
            mostrar();
            this.replicate();
        },
        replicate: function(){
            db.replicate.from(remote,{live:true,retry:true})
                .on('paused',function(info){
                mostrar();
            });
        },
        get: function(id){
            return db.get(id);
        }
    }
})

Vemos que el factory ‘db’ en la sección return publica tres métodos: init(), replicate() y get()
Por lo tanto, si el objeto db nos da algún error en alguna llamada en el controlador, debemos revisar esta parte del código para encontrar el error.

Lo que puede crear algo de confusión es que el factory se llama ‘db’ y luego internamente existe la variable ‘db’ que en realidad es un objeto de la clase PouchDB. En el controlador siempre debemos usar el objeto indicando el nombre del Factory.

Finalmente, regresando al concepto MVC de nuestro código, vemos que cada vez que encontramos un cambio en los datos, generamos un mensaje broadcast que es recibido en el controlador, como vemos en el controlador ‘newsController’ en el archivo controllers.js

.controller('newsController',function($scope,db){
    db.init();
	$scope.notas=[];
	$scope.$on('refrescar',function(event,news){
		$scope.$apply(function(){
			$scope.notas = news;
		})		
	})
})

Pueden ver que en la línea 5, definimos la lógica que se ejecutará al recibir el evento generado por el Modelo mediante el Factory db en el archivo services.js. Podrán notar que el evento es generado en el método mostrar:

        var mostrar = function(){
        db.allDocs({startkey:'news_\uffff',endkey:'news_',descending: true,include_docs:true})
                    .then(function(result){
                    $rootScope.$broadcast('refrescar',result.rows);
                });
    };

En la línea 10 generamos el mensaje incluyendo los registros que queremos mostrar como parámetro.

Este envío de mensajes es muy importante porque de lo contrario estaremos declarando y verificando el valor de variables de control a cada rato, lo cual no es bueno ni para respetar el modelo MVC ni para el mantenimiento de su código. Incluso, ya cuando tengan aplicaciones grandes, notarán que necesitarán pasar mensajes entre objetos que no necesariamente alteran la vista, por ejemplo si quieren registrar la posición del móvil y guardarla cada 15 minutos, tendrán que invocar a un servicio enviando un broadcast desde otro servicio que controla el tiempo. El mejor lugar para indicar la lógica de estos eventos que no alteran es en el archivo app.js que podríamos considerar como parte de la capa Controller.

En un próximo post veremos un poco de este manejo mediante la creación de servicios lo más parecido a las clases que utilizamos en programación orientada a objetos donde podremos identificar los datos por un lado y los métodos por otro diferenciando cuáles son públicos y cuáles privados.

Espero que con esto me puedan ayudar a corregir errores ya sean por no incluir el código, o porque de verás se metió un bug, aunque les aseguro que primero me aseguro que el código funciona antes de publicar el post.


  1. Reblogged this on Dinesh Ram Kali..

  2. Hasta esta parte que viene siendo la mitad del curso hasta ahora, he aprendido muchas cosas pero aún no me siento con confianza de moverle (con eso del scope rootScope me confundo, analizaré el codigo), pero viendo lo que dices que en las proximas partes hablas de creacion de servicios y se parecen a las clases utilizadas en POO, me emociona.

    saludos!

  1. 1 Ionic Framework, PouchDB y Cloudant: la combinación perfecta totalmente expuesta | Víctor Pease

    […] Part 6 […]




Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s



%d bloggers like this: