Meal Maker - I'm getting an error with my dishes.length

I keep getting the error:
/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:70
let i = Math.floor(Math.random() * dishes.length);
^

TypeError: Cannot read property ‘length’ of undefined
at Object.getRandomDishFromCourse (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:70:46)
at Object.generateRandomMeal (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:75:28)
at Object. (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:100:17)
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)

Here’s what I have:

const menu = {
  _courses: {
    appetizers: [],
    mains: [],
    desserts: [],
  },

    get appetizers() {
        return this._courses.appetizers
      },

    set appetizers (appetizers) {
      if (typeof appetizers === 'string' && appetizers.length > 0) {
          return this._courses.appetizers = appetizers
        } else {
          return 'Please enter a valid string for the appetizer name'
        }
      },

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

    set mains (mains) {
      if (typeof mains === 'string' && mains.length > 0) {
        return this._courses.mains = mains
      } else {
        return 'Please enter a valid string for the main name'
      }
    },

    get desserts () {
          return this.desserts
      }, 
      
    set desserts (desserts) {
        if (typeof desserts === 'string' && desserts > 0) {
          return this._courses.desserts = desserts
      } else {
        return 'Please enter a valid string for the dessert name'
      }
  },

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

  addDishToCourse (courseName, dishName, dishPrice) {
    const dish = {
      name: dishName,
      price: dishPrice
    };
    if (courseName === 'appetizers') {
      this._courses.appetizers.push(dish)
    } else if (courseName === 'mains'){
      this._courses.mains.push(dish)
    } else if (courseName === 'desserts'){
      this._courses.desserts.push(dish)
    } else {
      return 'Please specify your course name as: appetizer, main, or dessert'
    };
  },

  getRandomDishFromCourse (courseName) {
    const dishes = this._courses[courseName];
    let i = Math.floor(Math.random() * dishes.length);
    return dishes[i];
  },

  generateRandomMeal() {
    const appetizer = this.getRandomDishFromCourse('appetizer');
    const main = this.getRandomDishFromCourse('main');
    const dessert = this.getRandomDishFromCourse('dessert');
    const totalPrice = (this._courses.appetizers.dishPrice + this._courses.mains.dishPrice + this._courses.desserts.dishPrice);
    return `
      Appetizer: ${this._courses.appetizers.name}
      Main: ${this._courses.mains.name}
      Dessert: ${this._courses.desserts.name} 
      Total Price: ${this.totalPrice}`
  },
};

//appetizer menu items
menu.addDishToCourse('appetizer', 'egg rolls', 2.99);
menu.addDishToCourse('appetizer', 'fried pickles', 3.99);
menu.addDishToCourse('appetizer', 'chips and salsa', 3.89);
//main menu items
menu.addDishToCourse('main', 'sweet and sour chicken', 13.49);
menu.addDishToCourse('main', '10 oz. sirloin steak', 24.79);
menu.addDishToCourse('main', 'flautas', 12.99);
//dessert menu items
menu.addDishToCourse('dessert', 'fortune cookie', .12);
menu.addDishToCourse('dessert', 'chocolate lava cake', 4.29);
menu.addDishToCourse('dessert', 'fried ice cream', 4.99);

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


One issue seems to be that you are sometimes referencing the dish-names in singular and other times in plural. Go over the code and make sure to use either singular or plural consistently where it makes sense. You can use some strategic console.logs throughout the functions to ensure the correct data is passed along in the program to help you sort it out.

// Plural in the object (for example appetizers)
 _courses: {
    appetizers: [],
    mains: [],
    desserts: [],
  },

// Referencing in singular in code below (for example appetizer)
getRandomDishFromCourse (courseName) {
    const dishes = this._courses[courseName];
    let i = Math.floor(Math.random() * dishes.length);
    return dishes[i];
  },

  generateRandomMeal() {
    const appetizer = this.getRandomDishFromCourse('appetizer');
    const main = this.getRandomDishFromCourse('main');
    const dessert = this.getRandomDishFromCourse('dessert');
    const totalPrice = (this._courses.appetizers.dishPrice + this._courses.mains.dishPrice + this._courses.desserts.dishPrice);
    return `
      Appetizer: ${this._courses.appetizers.name}
      Main: ${this._courses.mains.name}
      Dessert: ${this._courses.desserts.name} 
      Total Price: ${this.totalPrice}`
  },
};


I keep getting EXACTLY the same problem but mine is coded differently;
let menu = {
_courses: {
appetizers: ,
mains: ,
dessert:
},
get appetizers() {
return this._courses.appetizers
},
set appetizers(appetizersIn) {
this._courses.appetizers = appetizersIn
},
get mains() {
return this._courses.mains
},
set mains(mainsIn) {
this._courses.mains = mainsIn
},
get desserts() {
return this._courses.desserts
},
set desserts(dessertsIn) {
this._courses.desserts = dessertsIn
},

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

addDishToCourse (courseName, dishName, dishPrice) {
const dish = {
name: dishName,
price: dishPrice,
}
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 randomly generated meal will start off with ${appetizer} followed by ${main} and topped off with a delicious portion of ${dessert}. This will cost £${totalPrice}

},

}
menu.addDishToCourse(‘appetizers’, ‘Crab Soup’, 5)
menu.addDishToCourse(‘appetizers’, ‘Lobster Claws’, 20)
menu.addDishToCourse(‘appetizers’, ‘Duck Pancakes’, 12)
menu.addDishToCourse(‘mains’, ‘Sirloin’, 15)
menu.addDishToCourse(‘mains’, ‘T-Bone’, 25)
menu.addDishToCourse(‘mains’, ‘Rump’, 10)
menu.addDishToCourse(‘dessert’, ‘Lemon Tart’, 5)
menu.addDishToCourse(‘dessert’, ‘Cheesecake’, 4)
menu.addDishToCourse(‘dessert’, ‘Pancakes and Syrup’, 7)

let meal = menu.generateRandomMeal()
console.log(meal)

Have spent like 2 hours looking over it and can’t find the issue

I also see a small issue with plural/singular misspelling that will cause trouble here. Here you have a key that is called dessert in the _courses object:

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

But when you are referencing this in much of the code, you are referencing desserts (in plural). So I would change this object key to desserts and see if that helps. If you still have trouble, enter some console.log-statements and see what values are getting passed into these functions as the code runs. Also, there is a </> function in this forum that helps with formatting the code correctly when posting and it makes it easier to troubleshoot.

1 Like

This was the first project I had to come to the forums asking for help with too. There are some concepts that are a bit tricky, and it’s really key to start using debugging techniques like console.log() as @mike7127143742 recommended to understand what your code is doing.

The TypeError is telling you that the getRandomDishFromCourse(courseName) fails because the .length method is being run on something undefined.

  1. What is .length being used on?
  2. The constant dishes was set to the value of this._courses[courseName]
  3. Below the line where dishes is declared, try a console.log(dishes) to see what is logged to the console.
  4. While you’re at it, try console.log(this._courses[courseName] and console.log(courseName) so you know what you’re dealing with.
  5. this._courses half should be fairly self explanatory, as this has been used throughout the code for getters and setters
  6. but what is returning with the second part - the [courseName]
  7. courseName was passed to getRandomDishFromCourse() by the generateRandomMeal() method.
  1. Within the generateRandomMeal() method, 'appetizer' is passed as an argument to the this.getRandomDishFromCourse() method (and becomes known as the courseName parameter in the getRandomDishFromCourse() method.
  2. Where did this 'appetizer' argument come from? What is it meant to do? Is this what is causing an undefined TypeError?

A separate problem to also consider:

  1. What does totalPrice in the generateRandomMeal() method return?
  2. dishPrice is used to calculate the constant totalPrice
  3. In the line above totalPrice put a console.log(this._courses.appetizers.dishPrice) to see what it is worth.
  4. Where does dishPrice come from?
  1. If dishPrice is the value half of the dish object’s key-value pair… how do you use the key to access the value (so it can be used in a calculation)?

The good news is that this project has brought you to the forums. As you do more projects, you will find yourself spending more time here - reading the posts of people with similar problems, troubleshooting, asking for help, and maybe helping others too.

Good luck :slight_smile:

3 Likes

Thanks for all the help. I got it working, It took way too long, but I got it