Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Cannot POST /produtos/salva

Olá, eu tive que parar de fazer o curso e voltei, só que agora não está salvando os dados, depois que eu tentei fazer a alteração do validator.

Carrega nodemon app, o banco, faltou alguma coisa pra rodar?

module.exports = function(app) {
   var listaProdutos = function(req,res){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);

        produtosBanco.lista(function(erros, resultados){
             res.format({
                html: function(){
                    res.render("produtos/lista",{lista:resultados});
                },
                json: function(){
                    res.json(resultados);
                }
            });
        });

        connection.end();
   };
    app.get('/produtos/form', function(req,res){
        res.render('produtos/form');
    });
    app.post('/produtos', function(req,res){
      var produto = req.body;

      var validatorTitulo = req.assert('titulo', 'Titulo é obrigatório');
      validatorTitulo.notEmpty();

      var erros = req.validationErrors();
      if(erros){
        res.render('produtos/form');
        return;
      }

        var connection = app.infra.connectionFactory();
        var produtosDAO = new app.infra.ProdutosDAO(connection);
        produtosDAO.salva(produto, function(erros, resultados){
            console.log(erros);
            res.redirect('/produtos');
        });
    })
ar express = require('express');
var load = require('express-load');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');

module.exports = function() {
    var app = express();
    app.set('view engine', 'ejs');
    app.set('views','./app/views');

    app.use(bodyParser.urlencoded({extended: true}));
    app.use(bodyParser.json());

    //req -> middlewareBodyParsers
    load('routes',{cwd: 'app'})
    .then('infra')
    .into(app);
    return app;
}
8 respostas

Pela descrição que você deu do problema, a dificuldade começou ao tentar validar os dados postados pelo formulário.

Olhando o seu arquivo de configuração, eu vi que você fez o require do módulo...

var expressValidator = require('express-validator');

mas, não está inserindo ele dentro do app.use. Por exemplo:

module.exports = function() {
    var app = express();
    app.set('view engine', 'ejs');
    app.set('views','./app/views');

    app.use(bodyParser.urlencoded({extended: true}));
    app.use(bodyParser.json());
    app.use(expressValidator); //Nova linha!

   //Resto do código omitido    
}

Tente fazer este ajuste.

Aqui tem um tutorial passo a passo de como usa o Validator

http://blog.ijasoneverett.com/2013/04/form-validation-in-node-js-with-express-validator/

Muito obrigada.

Talvez eu tenha que rever aulas anteriores, estou com dificuldade para entender qual função e arquivo depende do que e não consigo uma mensagem de erro mais explicativa.

A rota /produtos aparece cannot get e depois da alteração só fica carregando e não faz nada.

Tirando a validação ele aparece esse erro:

Cannot POST /produtos/salva

É como se ele não conseguisse gravar no banco de dados, o que pode ser um caminho de arquivo, código do banco de dados?

ProdutosDAO

function ProdutosDAO(connection){
    this._connection = connection;
}

 ProdutosDAO.prototype.lista = function(callback){
    this._connection.query('select * from livros', callback);
}

ProdutosDAO.prototype.salva = function(produto, callback){
    this._connection.query('insert into livros set ?', produto, callback);
}



module.exports = function(){
   return ProdutosDAO;
}

connectionFatory

var mysql  = require('mysql');

function createDBConnection(){
    return mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '',
        database: 'casadocodigo_nodejs'
    });
}

module.exports = function() {
    return createDBConnection;
}

Olhando o seu código, você não tem as rotas de "/produto" e "/produto/salva", por isso está aparecendo as mensagens de erro.

O "/produtos" (verbo GET) seria para listar os produtos do seu banco. Você pode fazer o seguinte teste, apenas para validar se a rota foi criada corretamente:

app.get('/produtos', function(req,res){
        res.send('Teste');
    });

Já o "/produtos/salva" seria para receber os dados do formulário. A programação que faz isso seria a que está em "/produto" (verbo POST, onde você utilizou o Validator).

Altere o HTML do formulário e faça um teste depois de fazer o seguinte ajuste na tag do formulário:

<form method="post" action="/produtos">

Uma outra alternativa seria ao invés de alterar o formulário, trocar o nome da rota para "/produtos/salva"

Não sei se eu entendi o teste, coloquei o teste no get, mudei o formulario, mas a rota produtos não está listando, aparece teste em http://localhost:3000/produtos/form.

Na rota /produtos http://localhost:3000/produtos

Cannot GET /produtos

Onde eu deveria criar essas rotas? Eu coloquei o post e o get no produtos.js.

no inicio funcionava, não sei qual alteração causou o erro.

Mudei a rota do get para testar e mudou a mensagem de erro. Isso tá dificil, porque estava funcionando. O que cria a rota é o app.get e post? Ele estava listando os resultados, de onde vem esse lista? Precisa do cliente-android rodando?

produtos.js

module.exports = function(app) {
   var listaProdutos = function(req,res){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);

        produtosBanco.lista(function(erros, resultados){
             res.format({
                html: function(){
                    res.render("produtos/lista",{lista:resultados});
                },
                json: function(){
                    res.json(resultados);
                }
            });
        });

        connection.end();
   };
    app.get('/produtos', function(req,res){
        res.render('produtos');
    });
    app.post('/produtos/salva', function(req,res){
      var produto = req.body;



      var connection = app.infra.connectionFactory();
      var produtosDAO = new app.infra.ProdutosDAO(connection);
        produtosDAO.salva(produto, function(erros, resultados){
          console.log(erros);
          res.redirect('/produtos');
        });
    })
}

Error: Failed to lookup view "produtos" in views directory "./app/views" at EventEmitter.render (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\application.js:579:17) at ServerResponse.render (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\response.js:960:7) at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\app\routes\produtos.js:20:13 at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5) at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:131:13) at Route.dispatch (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5) at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:277:22 at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:330:12) at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:10)

Nova alteração, consegui recuperar uma modificação anterior, adicionei e comentei a linha da rota produtos/form e voltou a funcionar. Acho que eu não entendi como funciona essa parte das rotas. Não entendi o que aconteceu:

Sem isso não estava listando:

app.get("/produtos", listaProdutos);

Por algum motivo eu tirei essa linha, teve algumas refatorações de código nos vídeos e acho que essa linha tinha saído...

module.exports = function(app) {
   var listaProdutos = function(req,res){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);

        produtosBanco.lista(function(erros, resultados){
             res.format({
                html: function(){
                    res.render("produtos/lista",{lista:resultados});
                },
                json: function(){
                    res.json(resultados);
                }
            });
        });

        connection.end();
   };


    app.get("/produtos", listaProdutos);

    app.get('/produtos/form', function(req,res){
      res.render('produtos/form');
    });
    app.post('/produtos/salva', function(req,res){

        var produto = req.body;
      console.log(produto)

        var connection = app.infra.connectionFactory();
        var produtosDAO = new app.infra.ProdutosDAO(connection);
        produtosDAO.salva(produto, function(erros, resultados){
            console.log(erros);
            res.redirect('/produtos');
        });
    })
}

Consegui fazer funcionar, agora quando eu coloco o titulo vazio aparece esse erro:

Error: Failed to lookup view "/produtos" in views directory "./app/views"
   at EventEmitter.render (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\application.js:579:17)
   at ServerResponse.render (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\response.js:960:7)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\app\routes\produtos.js:35:15
   at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
   at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:131:13)
   at Route.dispatch (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:112:3)
   at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:277:22
   at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:330:12)
   at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:10)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express-validator\lib\express_validator.js:355:5
   at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
   at trim_prefix (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:312:13)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:280:7
   at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:330:12)
   at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:10)
solução!

O arquivo principal da sua aplicação é o app.js, que fica dentro da pasta raiz da aplicação. É ele que faz o servidor subir. Dentro dele, você chama o arquivo de configuração, que fica dentro da pasta "config", o arquivo "express.js"

Nesse arquivo "express.js" você carrega o express e acopla os "middlewares" na aplicação, como o "body-parser" e o "express-validator". Neste arquivo que você informa onde você vai guardar as rotas (pasta "app/routes"), as views (pasta "app/views") e a conexão com o banco e a lógica para acessar os dados dos produtos (pasta "app/infra")

Dentro de "app/routes", fica cada arquivo de rota, ou seja, os endereços que você pode acessar. No caso do arquivo "app/routes/produtos", você pode ter os seguintes endereços:

module.exports = function(app){
    app.get('/produtos', function(req,res, next){
        //Programação
    });

    app.get('/produtos/form',function(req,res){
        //Programação
    });

    app.post('/produtos/salva',function(req,res){
        //Programação
    });    
}

O arquivo recebe a variavel "app" que veio do arquivo de configuraçao do express, e adiciona nele o endereço e o modo de acesso (verbo http). No exemplo acima, você vai ter "/produtos" e "/produtos/form" que podem ser acessados pela barra de endereços do navegador (get) e um endereço "/produtos/salva" que somente pode ser acessado postando dados pelo formulário (post)

Esse erro do "Error: Failed to lookup view "/produtos" está relacionado com as views. No arquivo de configuraçao do express ("express.js"), você informa a pasta onde ele tem que procurar as views.


 app.set('views', './app/views');

Dentro da pasta views, eu tenho uma pasta produtos, e dentro dela vou ter duas views, uma chamada "lista.ejs" e outra chamada "form.ejs".

Para puxar a view dentro do arquivo de rota, você usa o res.render.

 res.render('produtos/lista', variaveis);

ou

res.render('produtos/form', variaveis);

O primeiro parâmetro é o caminho da view. Ele procura dentro da pasta "views", de acordo com o que foi informado no arquivo de configuração.