Meal maker

#1

This has to be my least favorite project.

I am not able to resolve the error TypeError: Cannot read property ‘push’ of undefined"

I have go through all the meal maker forums and i cant seem to resolve this.

I am totally confused with this project and i dont see the point of setter method when the video walk through uses _courses[courseName].push(dishes) method to fill an array.

I also didnt understand the getRandomDish() I dont understand why the randomIndex is used and how is it calculated from the dish.length variable.

Please help and explain. Thank you for your time

#2

do you understand what this error message means? When you call push an array:

[].push('some value')

everything goes fine. However, such methods are data type specific, courses[courseName] gives undefined, calling push on undefined gives this error

you could use the setter method to do the pushing for you:

const myObj = {
  _someProp: [],
  get someProp(){
     return this._someProp;
  },
  set someProp(propIn){
    this._someProp.push(propIn)
  }
}

myObj.someProp = "some value"
console.log(myObj.someProp)

I believe this an added challenge, but then finally setters start to shine (doing some different then the default assign behavior)

to understand, i am afraid we need to fix this mistake first:

set mains(mains) {
    this._courses.mains = "mains";
},

if you know where to use the setter, you would overwrite the array into a string. Which is not desired

if we have an array, and we know the length, we can calculate a random number, this random number can then be used to access the array by index. This way, we get a random main course (or dessert/appetizers)

as for your actual error, there is plenty wrong with your getters. lets start here:

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

this getter is part of menu object. the menu object does not have appetizers, mains or desserts properties, thus this.appetizers (and the rest) are undefined in your _courses getter

next problem:

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

mains getter (and the other two), these getters are part of _courses object, thus this refers to _courses object. the courses object doesn’t have have a _courses object, thus this getter method also returns undefined.

The solution proposed by the exercise defines the appetizers, mains and desserts getters as part of the menu object (and not the _courses) object, so something like this:

const menu = {
  _courses: {
    appetizers: [],
    mains: [],
    desserts: [],
  },
  get appetizers() {
    return this._courses.appetizers;
  },
  // rest of code

this way, you can access appetizers directly in menu, even though the actual property is defined within the _courses object

personally, the getters and setters massively complicate this project, without adding too much value. You can do yourself and first get rid of the getters and setters. Then add them later if you feel like it

2 Likes
#3

Having looked at your code on github, you have some basic syntax errors with your curly braces { }.
Your _courses object needs it’s closing brace located before you start adding getters and setters.
You are also missing some comma’s.

Just my opinion, but if you’ll be meticulous about indentation and using ; at the end of your statements, your code becomes easier to read, and much easier to find and fix errors.

Go through your code, and see if you can fix these errors, and it should work more or less as expected. I’m including your code with the syntax errors fixed, but you should try to fix it yourself first.

let menu = {
  _courses: {
      appetizers: [],
      mains: [],
      desserts: [],
  }, 
  
  set appetizers(appetizers) {
    this._courses.appetizers = "appetizers";
  },
  
  get appetizers() {
    return this._courses.appetizers;
  },
  
  set mains(mains) {
    this._courses.mains = "mains";
  },
  
  get mains() {
    return this._courses.mains;
  },
    
  set desserts(desserts) {
    this._courses.desserts = "desserts";
  },
  
  get desserts() {
    return this._courses.desserts;
  },
    
  get courses(){
    return {
      appetizers : this.appetizers,
      main : 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}, ${dessert.name} and total bill is ${totalPrice}`;
  }
}
    
menu.addDishToCourse('appetizers',"salad", 3 );
menu.addDishToCourse('appetizers',"wings", 4 );
menu.addDishToCourse('appetizers',"fries", 2 );

menu.addDishToCourse('mains',"sphagetti", 5 );
menu.addDishToCourse('mains',"pasta", 5 );
menu.addDishToCourse('mains',"pizza", 6 );

menu.addDishToCourse('desserts',"ice-cream", 5 );
menu.addDishToCourse('desserts',"cake", 3 );
menu.addDishToCourse('desserts',"coffee", 2 );
    
const meal = menu.generateRandomMeal(); //Meal not Dish
console.log (meal);

Don’t get discouraged. Good luck!

1 Like
#4

Thank you for your time to review my code.

addDishToCourse(courseName,dishName,dishPrice){
    const dish = {
      name: dishName,
      price: dishPrice, 
      
   
    }
    
    return this._courses[courseName].push(dish);

I know what the push method does :slight_smile: I have declared dish and assigned it dishName and dishPrice. just cant figure out why does these values not get pushed into the array.

#5

thank you for reviewing my code.

I have made the corrections suggested

let menu = {
  _courses : {
  	appetizers: [],
  	mains: [],
  	desserts: [],
  },
#6

on this line:

return this._courses[courseName].push(dish);

this._courses will call the courses getter:

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

which returns appetizers, main and desserts. However, within this getter this.appetizers (and the other ones) are undefined given menu doesn’t have these properties

that is why in my previous answer i hammered on the getters and setters, you need to understand there flow, how to use them, otherwise implementing methods like addDishToCourse becomes really tricky

#7

You’re welcome! If you still need assistance, I suggest posting your code again, so we can see everything that’s going on.