segunda-feira, 16 de dezembro de 2013

REST - Aula Prática - Arrumar o Projeto e Listar os Dados

Na postagem anterior vimos como colocar os dados no MongoDB, só que ao rever os arquivos anteriores descobri que deixei algumas coisas um tanto mal organizadas (o que pode prejudicar lá na frente) então permita-me nesta postagem arrumar o projeto para finalizarmos nosso CRUD.

Qual editor utilizar?


Essa é uma dúvida que muitas pessoas me fazem. Qualquer um serve entre o NotePad++ ao Eclipse, prefiro usar um editor intermediário, como o Free JavaScript Editor que possui inclusive autocomplete de código. O mais famoso deles se chama Sublime Text, muitos professores que usam Mac o utilizam, existem versões para Windows e Linux também, só que o preço da licença (70 dólares) chega a assustar muitas pessoas.

Arrumar a Camada do Servidor


Trocamos o nome do arquivo do servidor para server.js e o colocamos na pasta \server, com a seguinte codificação:
if (!process.env.NODE_ENV) process.env.NODE_ENV='development'

var express = require('express'),
  routes = require('../routes'),
  livro = require('../dados/livroFuncoes.js');

var app = module.exports = express.createServer();

app.configure(function(){
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use('/css', express.static(__dirname + './../public/stylesheets'));
  app.use('/js', express.static(__dirname + './../public/javascripts'));
});

// Ambientes
app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
  app.use(express.errorHandler());
});

// Rotas do Sistema
app.get('/', routes.index);
app.get('/lista/livro', livro.listar);

// Ativar o Servidor
app.listen(3000);
console.log("Servidor está executando na porta %d em modo de %s", app.address().port, app.settings.env);
Na primeira linha, definimos o modo que o servidor é iniciado em development (desenvolvimento) ou production (produção), veja na seção ambientes as diferenças (aqui basicamente se mostrará ou não uma trilha de erro completa). Em seguida vemos as bibliotecas de uso e a configuração do servidor. O caminho das rotas de acesso e o inicio do servidor na porta 3000.

Para completar a definição desses caminhos, na pasta \routes existe por padrão um arquivo chamado index.js, devemos deixá-lo com a seguinte codificação:
var fs = require('fs'); 
 
exports.index = function(req, res){
  fs.readFile('../views/index.html', function(error, content) {
    if (error) {
      res.writeHead(500);
      res.end();
    } else {
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end(content, 'utf-8');
    }
  });
};
Este arquivo contém os caminhos (as rotas) do sistema, e indica qual arquivo é chamado, no servidor deixamos apenas as indicação dos caminhos para este arquivo.

Arrumar a Camada de Dados


Agora vamos organizar os arquivos que fazem a comunicação com o banco MongoDB. Na pasta principal \app criamos uma pasta chamada \dados e adicionamos o arquivo livroFuncoes.js com a seguinte codificação:
banco = require('./livroDb.js'),
exports.listar = function (req, res){
  livroModel.find().exec(function(err, livro) {
    if (err) { return console.log(err); }
    return res.json(livro);
  });
} 
Este arquivo é responsável por todas as funções de acesso a tabela (em breve teremos a inclusão, alteração, exclusão), neste momento, possui uma única função que retorna uma listagem dos dados do arquivo em formato Json. Criamos, também nesta pasta, um arquivo chamado livroDb.js com a seguinte codificação:
mongoose = require('mongoose');

// Conexão com o Banco 
mongoose.connect('mongodb://localhost:27017/livro');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function calbckcallback() {
    init();
});

function init() {
    schema = new mongoose.Schema({
      nome: {type: String, unique: true},
      autor: String
    });
    livroModel = mongoose.model('Livro', schema);
}
Este era o nosso antigo arquivo db.js. Aqui temos uma conexão com o banco e a função init() que determina como é a estrutura da tabela.

Arrumar a Camada de Visão


Copiamos todo o conteúdo da pasta \sist para a pasta \views. Nesta pasta \views:
  • Copiamos o arquivo \css\bootstrap.css para a pasta \public\stylesheets e eliminamos a pasta \css.
  • Copiamos os arquivos \javascript\controllers.js, \lib\angular.min.js e \lib\angular.min.js.map para a pasta \public\javascripts e eliminamos as pastas \javascript e \lib.

Na pasta \views criamos o arquivo index.html com a seguinte codificação:
<!doctype html>
<html>
 <head>
  <meta Charest="UTF-8">
  <title>Teste AngularJS/NodeJS</title>
  <link rel="stylesheet" type="text/css" href="/css/bootstrap.css">
  <script src="/js/angular.min.js"></script>
  <script src="/js/controllers.js"></script>
 </head>
 <body ng-app ng-controller="ListaCtrl">
  <div class="container">
   <h2>Meus Livros</h2>
   <label for="criteria" class="label" style="margin-right:6px;">Pesquisar</label>
   <input id="criteria" type="search" ng-model="criteria">
   <table class="table table-striped table-hover table-bordered">
    <thead>
     <th>Título</th>
     <th>Autor(es)</th>
    </thead>
    <tr ng-repeat="livro in livros | filter:criteria | orderBy:'nome'"
        ng-click="select(livro)" ng-class="{'info': nome == livro.nome}">
     <td>{{livro.nome}}</td>
     <td>{{livro.autor | uppercase}}</td>
    </tr>
   </table>
  </div>
 </body>
</html>
Mostramos uma listagem principal dos dados conforme vimos anteriormente no arquivo hello.html. Preferi republicá-lo neste outro arquivo para completarmos nossa padronização da codificação e não restar mais nenhuma dúvida. O próximo arquivo fica na pasta \views\javascript, é o arquivo controllers.js e possui a seguinte codificação:
function ListaCtrl($scope, $http) {
  $scope.nome = '';
  $http.get('/lista/livro').success(function(data) {
    $scope.livros = data;
  })
  $scope.select = function(livro) {
    $scope.nome = livro.nome;
  }
}
Esta função acessa o Json e obtém os dados para carregar a variável $scope.livros para o preenchimento da tabela. A função select será utilizada quando na seleção de um registro (para as funções de alteração e exclusão).

Nossa estrutura final ficou com o seguinte formato:
/app - Pasta raiz do projeto
 /dados - Camada de Dados
  livroDB.js - Acesso ao MongoDB
  livroFuncoes.js - Funções da tabela "livros"
 /public
  /images - imagens do projeto
  /javascripts - bibliotecas e controllers
   angular.min.js - Biblioteca do AngularJS
   angular.min.js.map - Mapeamento do AngularJS
   controllers - Arquivo de Controller para o AngularJS
  /stylesheets
   bootstrap.css - Arquivo de estilos do Bootstrap
   style.css - Arquivo de estilos criado por padrão
 /routes
  index.js - Contém as rotas do sistema
 /server - Camada do Servidor 
  server.js - Inicia o servidor (na linha de comando: supervisor server.js)
 /views - Camada de Visão
  index.html - Janela principal do sistema
A única pasta que está faltando é a \node_modules que são os módulos utilizados como: express, mongoose e supervisor. Essa organização foi necessária para podermos continuar com nossos estudos.

Com esta implementação podemos ver os dados que foram inseridos no banco (ou seja, concluímos a letra R), na próxima postagem continuaremos nosso CRUD com a inserção dos dados na tabela.

Obrigado e até a próxima
Fernando Anselmo

0 comentários:

Postar um comentário