Help me on my js Meal Maker project

Hello all, I am working on the project ‘Meal Maker’ and cant get my code to run. Please review it and help me find my problem.

Here is my code.

const menu = {
  _courses :{
    _appetizers: [],
    _mains: [],
    _deserts: [],
  },
  get appetizers() {
return this._appetizers
  },
set appetizers(appetizersIn) {
this._appetizers = appetizersIn;
},
get mains(){
  return this._appetizers = appetizersIn;
},
set mains(mainsIn) {
this._mains = mainsIn;
}, 
get desserts() {
return this._desserts;
},
set desserts(dessertsIn) {
  this._desserts = dessertsIn;
},

get courses() {
  return { 
    appetizers: this._courses.appetizers, mains: this._courses.mains, 
    desserts: this._courses.desserts,
};
},
// .................................
addDishtoCourse (courseName, dishName, dishPrice) {
const dish = {
  name: dishName,
  price: dishPrice
}
return this.courses[courseName].push(dish)
},
getRandomDishFromCourse(courseName) {
  const dishes = this.courses[courseName];
  const randomIndex = Math.random(Math.floor() * dishes.length)
  return dishes[randomIndex];
},

generateRandomMeal() {
  const appetizer = this.getRandomDishFromCourse('appetizers');
  const main = this.getRandomDishFromCourse('mains');
  const dessert = this.getRandomDishFromCourse('deserts')
  const totalPrice = appetizer.price + mains.price + desserts.price;
  return `Your meal is ${appetizer.name}, ${main.name}, and ${desserts.name}, The price is ${totalPrice.toFixed(2)}.`
},
};

menu.addDishtoCourse('appetizers', 'salad', 4.00)
menu.addDishtoCourse('appetizers', 'wings', 6.00)
menu.addDishtoCourse('appetizers', 'salad', 5.00)

menu.addDishtoCourse('mains', 'steak', 16.25)
menu.addDishtoCourse('mains', 'salmon', 18.00)
menu.addDishtoCourse('mains', 'tofu', 12.20)

menu.addDishtoCourse('desserts', 'ice cream', 2.50)
menu.addDishtoCourse('desserts', 'brownie', 3.50)
menu.addDishtoCourse('desserts', 'cookies', 2.50)

const meal = menu.generateRandomMeal();
console.log(meal);

Here is the error.

/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:38
return this.courses[courseName].push(dish)
^

TypeError: Cannot read property ‘push’ of undefined
at Object.addDishtoCourse (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:38:32)
at Object. (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:55:6)
at Module._compile (module.js:571:32)
at Object.Module._extensions…js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:427:7)
at startup (bootstrap_node.js:151:9)

this error is very often caused by the fact that you attempt to use a key/property which does not exists on the object, so the first debugging step would be to log the available keys and the key you attempt to use:

addDishtoCourse (courseName, dishName, dishPrice) {
const dish = {
  name: dishName,
  price: dishPrice
}
console.log(Object.keys(this.courses), courseName);
return this.courses[courseName].push(dish)
},

which doesn’t seem to be the problem in your case. Then the next suspect would the getters and setters, which is when I noticed this:

get mains(){
  return this._appetizers = appetizersIn;
},

your getter for mains look off. You are setting appetizers within mains getter?

Finally, your getters are problems, starting with your courses getter:

get courses() {
  return { 
    appetizers: this._courses.appetizers, 
    mains: this._courses.mains, 
    desserts: this._courses.desserts,
};
},

the _courses object does not have appetizers property (same for mains and desserts)

I think you are pretty close, except you made your appetizers (mains and desserts) getters part of the menu object, while they should be part of the _courses object.

2 Likes

Hey, thanks for the response. I went over your suggestions and revised my getters and setters to try and fix the problem. It is still not running, here is the revised code.

const menu = {
  _courses : {
    _appetizers: [],
    _mains: [],
    _deserts: [],
  },
  get appetizers() {
return this._courses.appetizers
  },
get mains() {
  return this._courses.mains;
},
get desserts() {
  return this._courses.desserts
},
set appetizers(appetizers) {
this._courses.appetizers = appetizers;
},
set mains(mains) {
this._courses.mains = mains;
}, 
set desserts(desserts) {
  this._courses.desserts = desserts;
},

get courses() {
  return { 
    appetizers: this._appetizers, 
    mains: this._mains, 
    desserts: this._desserts,
}
},
// .................................
addDishtoCourse(courseName, dishName, dishPrice) {
const dish = {
  name: dishName,
  price: dishPrice,
}
return this.courses[courseName].push(dish)
},
getRandomDishFromCourse(courseName) {
  const dishes = this.courses[courseName];
  const randomIndex = Math.floor(Math.random() * dishes.length)
  return dishes[randomIndex];
},
generateRandomMeal() {
  const appetizer = this.getRandomDishFromCourse('appetizers');
  const main = this.getRandomDishFromCourse('mains');
  const dessert = this.getRandomDishFromCourse('deserts')
  const totalPrice = appetizer.price + mains.price + desserts.price;
  return `Your meal is ${appetizer.name}, ${main.name}, and ${desserts.name}, The price is ${totalPrice}.`
}
};

menu.addDishtoCourse('appetizers', 'salad', 4.00)
menu.addDishtoCourse('appetizers', 'wings', 6.00)
menu.addDishtoCourse('appetizers', 'salad', 5.00)

menu.addDishtoCourse('mains', 'steak', 16.25)
menu.addDishtoCourse('mains', 'salmon', 18.00)
menu.addDishtoCourse('mains', 'tofu', 12.20)

menu.addDishtoCourse('desserts', 'ice cream', 2.50)
menu.addDishtoCourse('desserts', 'brownie', 3.50)
menu.addDishtoCourse('desserts', 'cookies', 2.50)

const meal = menu.generateRandomMeal();
console.log(meal);

Im really not sure what the problem is.

Also just realized I has a spelling error in desserts at the top, fixed it now. Was not the main issue.

Ive tried running the ._courses in and out of my getters and it did not fix the problem. I have them in there because the person in the project walk through has ._courses in his getters, do you think I should just leave it out?

If I look at this:

const menu = {
  _courses : {
    _appetizers: [],
    _mains: [],
    _deserts: [],
  },
  get appetizers() {
return this._courses.appetizers
  },

in the getter you try to access this._courses.appetizers property, which does not exists. I only see a _appetizers property in the _courses object

Like this?

const menu = {
  _courses : {
    _appetizers: [],
    _mains: [],
    _deserts: [],
  },
  get appetizers() {
return this._courses._appetizers
  },
get mains() {
  return this._courses._mains;
},
get desserts() {
  return this._courses._desserts
},
set appetizers(appetizers) {
this._courses.appetizers = appetizers;
},
set mains(mains) {
this._courses.mains = mains;
}, 
set desserts(desserts) {
  this._courses._desserts = desserts;
},

get courses() {
  return { 
    appetizers: this._appetizers, 
    mains: this._mains, 
    desserts: this._desserts,
}
},
// .................................
addDishtoCourse(courseName, dishName, dishPrice) {
const dish = {
  name: dishName,
  price: dishPrice,
}
return this.courses[courseName].push(dish)
},
getRandomDishFromCourse(courseName) {
  const dishes = this.courses[courseName];
  const randomIndex = Math.floor(Math.random() * dishes.length)
  return dishes[randomIndex];
},
generateRandomMeal() {
  const appetizer = this.getRandomDishFromCourse('appetizers');
  const main = this.getRandomDishFromCourse('mains');
  const dessert = this.getRandomDishFromCourse('deserts')
  const totalPrice = appetizer.price + mains.price + desserts.price;
  return `Your meal is ${appetizer.name}, ${main.name}, and ${desserts.name}, The price is ${totalPrice}.`
}
};

menu.addDishtoCourse('appetizers', 'salad', 4.00)
menu.addDishtoCourse('appetizers', 'wings', 6.00)
menu.addDishtoCourse('appetizers', 'salad', 5.00)

menu.addDishtoCourse('mains', 'steak', 16.25)
menu.addDishtoCourse('mains', 'salmon', 18.00)
menu.addDishtoCourse('mains', 'tofu', 12.20)

menu.addDishtoCourse('desserts', 'ice cream', 2.50)
menu.addDishtoCourse('desserts', 'brownie', 3.50)
menu.addDishtoCourse('desserts', 'cookies', 2.50)

const meal = menu.generateRandomMeal();
console.log(meal);

yea, looks a lot better. Not totally though, your courses getter is a problem:

get courses() {
  return { 
    appetizers: this._appetizers, 
    mains: this._mains, 
    desserts: this._desserts,
}

menu object doesn’t have a _appetizers property, you could use the getter here, so you don’t have to access the nested property

also your setters are somewhat problematic, again some access non-existing properties and don’t push elements into the array (they overwrite the array with whatever value you assign)

Ok thanks, so what i’m getting at is I need to take away the underscores before appetizers, mains and desserts in the courses getter ?
Like so,
get courses() {
return {
appetizers: this.appetizers,
mains: this.mains,
desserts: this.desserts,
}
Also, I appreciate your help a lot! I am very determined to get this project working.

1 Like

yes, but its also very important to understand why you make this change. Now you use the properties created by the getters. Which are part of the menu object

1 Like

Ok, could you point me in the right direction on how to fix my setters?

the setters should call .push() to change the default assignment behavior.

Like this? const menu = {
_courses : {
_appetizers: ,
_mains: ,
_desserts: ,
},
get appetizers() {
return this._courses._appetizers
},
get mains() {
return this._courses._mains;
},
get desserts() {
return this._courses._desserts
},
set appetizers(appetizer) {
this._appetizers.push(appetizer);
},
set mains(main) {
this._mains.push(main);
},
set desserts(dessert) {
this._desserts.push(dessert);
},

get courses() {
return {
appetizers: this.appetizers,
mains: this.mains,
desserts: this.desserts,
}
},
// …
addDishtoCourse(courseName, dishName, dishPrice) {
const dish = {
name: dishName,
price: dishPrice,
}
return this.courses[courseName].push(dish)
},
getRandomDishFromCourse(courseName) {
const dishes = this.courses[courseName];
const randomIndex = Math.floor(Math.random() * dishes.length)
return dishes[randomIndex];
},
generateRandomMeal() {
const appetizer = this.getRandomDishFromCourse(‘appetizers’);
const main = this.getRandomDishFromCourse(‘mains’);
const dessert = this.getRandomDishFromCourse(‘desserts’)
const totalPrice = appetizer.price + mains.price + desserts.price;
return Your meal is ${appetizer.name}, ${main.name}, and ${desserts.name}, The price is ${totalPrice}.
}
};

menu.addDishtoCourse(‘appetizers’, ‘salad’, 4.00)
menu.addDishtoCourse(‘appetizers’, ‘wings’, 6.00)
menu.addDishtoCourse(‘appetizers’, ‘salad’, 5.00)

menu.addDishtoCourse(‘mains’, ‘steak’, 16.25)
menu.addDishtoCourse(‘mains’, ‘salmon’, 18.00)
menu.addDishtoCourse(‘mains’, ‘tofu’, 12.20)

menu.addDishtoCourse(‘desserts’, ‘ice cream’, 2.50)
menu.addDishtoCourse(‘desserts’, ‘brownie’, 3.50)
menu.addDishtoCourse(‘desserts’, ‘cookies’, 2.50)

const meal = menu.generateRandomMeal();
console.log(meal);

getting this error now,
/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:50
const totalPrice = appetizer.price + mains.price + desserts.price;
^

ReferenceError: mains is not defined
at Object.generateRandomMeal (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:50:40)
at Object. (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:67:19)
at Module._compile (module.js:571:32)
at Object.Module._extensions…js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:427:7)
at startup (bootstrap_node.js:151:9)

Never Mind I took the s’s off main and dessert in my totalPrice variable and it seems to be working now! thanks for your help :slight_smile:

the error is caused by the fact that you declare a variable:

const main = this.getRandomDishFromCourse('mains');

and then later use the plural name of the variable. Seems you figured that out

I don’t think your setters would work, looking at your code:

set appetizers(appetizer) {
this._appetizers.push(appetizer);
},

this is the menu object, which doesn’t have an _appetizers property, so you would either need to use the getter or access the property nested within the courses object

So by taking away the underscore in the this._appetizers.push(appetizer) would allow me to use the getter, correct?

This is what ive got,

const menu = {
  _courses : {
    _appetizers: [],
    _mains: [],
    _desserts: [],
  },
  get appetizers() {
return this._courses._appetizers
  },
get mains() {
  return this._courses._mains;
},
get desserts() {
  return this._courses._desserts
},
set appetizers(appetizer) {
this.appetizers.push(appetizer);
},
set mains(main) {
this.mains.push(main);
}, 
set desserts(dessert) {
  this.desserts.push(dessert);
},

get courses() {
  return { 
    appetizers: this.appetizers, 
    mains: this.mains, 
    desserts: this.desserts,
}
  },
// .................................
addDishtoCourse(courseName, dishName, dishPrice) {
const dish = {
  name: dishName,
  price: dishPrice,
}
return this.courses[courseName].push(dish)
},
getRandomDishFromCourse(courseName) {
  const dishes = this.courses[courseName];
  const randomIndex = Math.floor(Math.random() * dishes.length)
  return dishes[randomIndex];
},
generateRandomMeal() {
  const appetizer = this.getRandomDishFromCourse('appetizers');
  const main = this.getRandomDishFromCourse('mains');
  const dessert = this.getRandomDishFromCourse('desserts')
  const totalPrice = appetizer.price + main.price + dessert.price;
  return `Your meal is ${appetizer.name}, ${main.name}, and ${dessert.name}, The price is ${totalPrice}.`
}
};

menu.addDishtoCourse('appetizers', 'salad', 4.00)
menu.addDishtoCourse('appetizers', 'wings', 6.00)
menu.addDishtoCourse('appetizers', 'salad', 5.00)

menu.addDishtoCourse('mains', 'steak', 16.25)
menu.addDishtoCourse('mains', 'salmon', 18.00)
menu.addDishtoCourse('mains', 'tofu', 12.20)

menu.addDishtoCourse('desserts', 'ice cream', 2.50)
menu.addDishtoCourse('desserts', 'brownie', 3.50)
menu.addDishtoCourse('desserts', 'cookies', 2.50)

const meal = menu.generateRandomMeal();
console.log(meal);

yes, and we could even take out the underscore on the courses properties:

  _courses : {
    appetizers: [],
    mains: [],
    desserts: [],
  },

and then update our getters accordingly:

  get appetizers() {
return this._courses.appetizers
  },
get mains() {
  return this._courses.mains;
},
get desserts() {
  return this._courses.desserts
},

if you understand why we can make this change, you have a good understanding of getters and setters :slight_smile:

Ok , thanks for helping me!

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