Api and microservices - Exercise Tracker Project - Persisting users / logs / exercises on Arrays?

Hello to everyone,

I am trying to solve the “Exercise Tracker” project by persisting the data in arrays instead of mongodb:

  • It’s possible?
  • Can the test be passed this way or is it mandatory to do so in mongodb?

This is the code that I am testing now and that technically solves almost all the tests, but it does not pass the tests

const express = require('express')
const app = express()
const cors = require('cors')
const bodyParser = require('body-parser');
require('dotenv').config()

app.use(cors())
app.use(express.static('public'))

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

let users = [];
let exercises = [];

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/views/index.html')
});

app.post('/api/users', function(req, res){
let _id = Date.now().toString();
let username = req.body.username;

  if(username === ''){
  res.json({error: 'Invalid Username'});
  return;
}
  
  users.push({_id, username, count:0, log:[]});
  res.json({username, _id});
});

app.post('/api/users/:_id/exercises', function(req, res){
  if(req.body[':_id'] === ''){
  res.json({error: 'Invalid _id'});
  return;
}
  let user = users.find(user => user._id === req.body[':_id']);
  if(typeof user === 'undefined'){
      res.json({error: `Not Found _id:${req.body[':_id']}`});
      return;
  }

  const id = req.params._id
  const duration = parseInt(req.body.duration)
  const description = req.body.description
  const date = req.body.date ? new Date(req.body.date).toDateString() : new Date().toDateString()

  //const date = req.body.date ? 'Mon Jan 01 1990' : 'Thu Nov 04 2021'

    const exercise = {
    date,
    duration,
    description
  };

  user.count = user.count + 1;
  user.log.push(exercise);

  const updatedExercise = {
    _id: id,
    username: user.username,
    ...exercise
  }

  exercises.push(updatedExercise);
  
  res.json(updatedExercise);
  
});

app.get('/api/users/:_id/logs', function(req, res){

  var user = users.find(user => user._id === req.params._id);
  if(typeof user === 'undefined'){
      res.json({error: `Not Found _id:${req.params._id}`});
      return;
  }
  res.json(user);
});
    
app.get('/api/users', function(req, res){
  res.json(users);  
});

app.get('/api/exercises', function(req, res){
  res.json(exercises);  
});

app.get('/api/logs', function(req, res){
  res.json(users);  
});


const listener = app.listen(process.env.PORT || 3000, () => {
  console.log('Your app is listening on port ' + listener.address().port)
})

Yes, it is possible to persist the data in arrays instead of MongoDB. The tests can be passed this way, although using MongoDB provides more robustness and scalability for storing and querying the data.

Your code seems to be handling the routes correctly and storing the data in the arrays, but there might be some issues in the implementation.

One issue that I see is in the /api/users/:_id/exercises route, where you are trying to access the _id from the body using req.body[':_id']. However, the _id should be accessed from the route parameters using req.params._id.

Another issue is in the same route, when you are trying to create a new exercise. The date should be set to the current date if no date is provided in the request, but you are using new Date().toDateString(). You should use new Date().toUTCString() instead to get the correct date format.

I hope this helps! Let me know if you have any further questions.

2 Likes

That depends on what you mean by persist. It will persist in memory for as long as the server is running. It will not persist as data does in a DB.

I would suggest you use a DB for all the backend challenges that require data to be stored and retrieved. Learning to use a DB is in part the point of the challenges.

You wouldn’t create a site that lets people store their data only to have it all disappear when the server goes down or reboots.

2 Likes

I agree with you @lasjorg , I will try to finish the test with the 2 options (array and mongo)

thanks for your comments

I just did the exam tests with the following code:

const express = require('express')
const app = express()
const cors = require('cors')
const bodyParser = require('body-parser');
require('dotenv').config()

app.use(cors())
app.use(express.static('public'))

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

let users = [];
let exercises = [];

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/views/index.html')
});

app.post('/api/users', function(req, res){
let _id = Date.now().toString();
let username = req.body.username;

  if(username === ''){
  res.json({error: 'Invalid Username'});
  return;
}
  
  users.push({_id, username, count:0, log:[]});
  res.json({username, _id});
});

app.post('/api/users/:_id/exercises', function(req, res){
  if(req.params._id === ''){
  res.json({error: 'Invalid _id'});
  return;
}
  let user = users.find(user => user._id === req.params._id);
  if(typeof user === 'undefined'){
      res.json({error: `Not Found _id:${req.params._id}`});
      return;
  }

  const id = req.params._id
  const duration = parseInt(req.body.duration)
  const description = req.body.description
  //const date = req.body.date ? new Date(req.body.date).toUTCString() : new Date().toDateString()
  //const date = req.body.date ? 'Mon Jan 01 1990' : 'Thu Nov 04 2021'

  const date = req.body.date ? new Date(req.body.date).toDateString() : new Date().toDateString()

    const exercise = {
      date: date,
      duration: duration,
      description: description
  };

  //console.log(typeof(date));
  //console.log(date);
  
  user.count = user.count + 1;
  user.log.push(exercise);

  const updatedExercise = {
    _id: id,
    username: user.username,
    ...exercise
  }

  exercises.push(updatedExercise);
  
  res.json(updatedExercise);
  
});

app.get('/api/users/:_id/logs', function(req, res){

const { from, to, limit } = req.query
//console.log(from, to, limit)
  
  var user = users.find(user => user._id === req.params._id);
 
  if(typeof user != 'undefined'){

    if(from || to || limit){
      const logs = user.log
      /*
      const filterLogs = logs
      .filter(log => 
        (from && new Date(log.date).toISOString().split('T')[0] >= from) && 
        (to && new Date(log.date).toISOString().split('T')[0] <= to))
      */
      
      const filterLogs = logs
        .filter(
          log => {
            const formattedLogDate = (new Date(log.date)).toISOString().split('T')[0]
            return true
          }
        )
      const slicedLogs = limit ? filterLogs.slice(0, limit) : filterLogs
      //console.log(slicedLogs)
      user.log = slicedLogs
    }
    
    res.json(user)
  
  }else{
    
    res.json({error: `Not Found _id:${req.params._id}`});
    return; 
    
  }
});
    
app.get('/api/users', function(req, res){
  res.json(users);  
});

app.get('/api/exercises', function(req, res){
  res.json(exercises);  
});

app.get('/api/logs', function(req, res){
  res.json(users);  
});


const listener = app.listen(process.env.PORT || 3000, () => {
  console.log('Your app is listening on port ' + listener.address().port)
})

To me it’s not filtering correctly the contents of the array, but the last test passed!!!

Maybe a bug in the test?

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.