Meal Maker .push(dish) doesnt work

Hi! my first time writing here, please let me know how can I ask question better ! But here it is:
I’m getting this error:

/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:37
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:37:39)
at Object. (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:54:8)
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)

I checked everything I could, but can’t find the problem. I think I get undefined somewhere but I just can’t see it yet, please help?

link to the project:
https://www.codecademy.com/paths/web-development/tracks/web-dev-js-arrays-loops-objects/modules/learn-javascript-objects/projects/meal-maker

and my code

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(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) {
      let dish = {
        name: dishName,
        price: dishPrice
      };
      return this._courses[courseName].push(dish);
    },
    getRandomDishFromCouse(courseName) {
      const dishes = this._courses[courseName];
      const randomIndex = Math.floor(Math.random() * dishes.length);
      return dishes[randomIndex];
    },
    generateRandomMeal() {
      const appetizer = this.getRandomDishFromCourse('appetizer');
      const main = this.getRandomDishFromCourse('main');
      const dessert = this.getRandomDishFromCourse('dessert');
      const totalPrice = appetizer.price + main.price + dessert.price;
      return `your meal is ${appetizer.name}, ${main.name}, ${dessert.name} and total price is ${totalPrice}`;
    }
  };
  
  
  menu.addDishToCourse('appetizer', 'salad', 12.00);
  menu.addDishToCourse('appetizer', 'wings', 14.00);
  menu.addDishToCourse('appetizer', 'fries', 5.00);
  
  menu.addDishToCourse('main', 'steak', 15.00);
  menu.addDishToCourse('main', 'salmon', 17.00);
  menu.addDishToCourse('main', 'tofu', 12.00);
  
  menu.addDishToCourse('dessert', 'coffe', 5.00);
  menu.addDishToCourse('dessert', 'ice-cream', 5.00);
  menu.addDishToCourse('dessert', 'cake', 7.00);
  
  let meal = menu.generateRandomMeal();
  console.log(meal);

Hello, @jenyakapustian348166, and welcome to the forums!

The error message tells you exactly where.
this._courses[courseName] is undefined, so the .push() method is not available. The question then becomes why is it undefined? Look at each piece. this refers to the menu object, so it should be defined. Is there a this or menu._courses defined? Yes. Here:

So, what’s left? [courseName] What value is being passed as an argument to your method that the parameter courseName gets assigned to?

Using console.log() statements to make observations while your code is running helps a great deal. We could answer the question above by using one here:

1 Like

Off topic

Something that has always puzzled me is why object destructuring is not introduced in the course, or at least as a hint in the project narrative. Further to that, why have different names in the parameters than in the returned object? It blocks the way to destructuring.

addDishToCourse(courseName, name, price) {
  this._courses[courseName].push( { name, price } )
},
3 Likes

Thank you Mr.midlinder! The case was that there was a mistake later in the code when I was passing value of courseName, set up a trap for myself haha
appetizer instead of appetizers, common! lol
Thanks!

1 Like

Those missing s's are the cause of almost every Meal Maker question in the forums. Staring at code looking for spelling errors is not an efficient debugging method, however. Learning to interpret error messages, and how to observe what our code is doing is a much better process for debugging. Happy coding!

Off topic

Another thing that isn’t talked about in the narrative is how nested objects present with different context.

menu = {
  _courses: {
    _appetizers: [],
...

Those are three different contexts. Executable code is scoped to its context. Of the three, the two parent objects can be an execution context to get an appetizer.

_courses context

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

or,

menu context

menu = {
  _courses: {
    appetizers: []
  },
  get appetizers () {
    return this._courses.appetizers
  }
  ...
}
1 Like

It would be nice if this project were overhauled for sure.

Off topic

What is with the getters and setters? They don’t even get used. A complete waste of time and learning energy. All the project needs to make it interesting is to drop them all (except get courses) and work to a successful conclusion with the rest of the code. Notwithstanding the narrative will speak about the execution context in its multiple domains.

1 Like