Meal Maker - make use of the setters for the courses

https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-javascript-syntax-part-ii/modules/fecp-learn-javascript-syntax-objects/projects/meal-maker

VS Code Note: I can debug normal methods, but my code is not stepping into the set appetizers() method. This suggests that the way I am calling it is wrong. See below.

I have completed this project except for the setters. They were not called in the solution, so it was not a problem.

Neither the project-steps nor the video make use of the getter or setters (of appetizers, mains, desserts) other than tell to you try your getters and setter.s The getter of each of those is clear. But I am not sure what the setter is supposed to do. For example: (from step 4 of the Menu project.)

  set appetizers(appetizersIn) {
    return this._courses.appetizers = appetizers;
  },

Is the purpose of this setter to initialize or replace what is currently the array of dish objects in menu._courses.appetizers or is it to add to appetizers? It looks like, in the setter, we must push an appetizer dish object but return an array of dishes. Here is my attempt to set the course appetizers by just pushing an additional dish.

//this is what appetizers consists of before calling the setter.
[
  { name: 'nachos', price: 6 },
  { name: 'stuffed mushrooms', price: 5.99 },
  { name: 'green leaf salad', price: 7.5 }
]

//this is the setter
  set appetizers(dish) {
    this._courses.appetizers.push(dish);
    return (this._courses.appetizers);
  }
[edit] I forgot menu. in front of appetizers
//this is how I called it
menu.appetizers = {name: 'crab  cakes', price: 7.75 };  //it now works as expected.

Updating an array in the backing variable cannot be done with an assignment in the setter. The setter must use array.push(item) so that it does not overwrite the array.

obj = {
  _prop = [],
  get prop () {
    return this._prop
  },
  set prop (item) {
    this._prop.push(item)
  }
}

obj.prop = 'red'
obj.prop = 'green'
obj.prop = 'blue'

console.log(obj.prop)
// [ 'red', 'green', 'blue' ]

For the record, the argument for the setter must be a single value. For instance, we cannot use a rest parameter…

obj = {
  _prop = [],
  get prop () {
    return this._prop
  },
  set prop (...item) {
    this._prop.push(item)
  }
}
​ Uncaught SyntaxError: Setter function argument must not be a rest parameter

There may be a way to accept an array as the argument but that will have to be unpacked else the array will get pushed, not the items. We cannot unpack with a spread operator, as far as I can tell.

Above we use the most obvious, one call per value added.

I edited the post. I already did use push, but I was not calling it correctly. I left off ‘menu.’ The setter now works as expected.

**menu**.appetizers = {name: 'crab  cakes', price: 7.75 };

Thanks for the reply.

1 Like

Also for the record, a setter does not return anything since nothing is expected at the caller (which is a straight forward assignment).

Aside

One would do well to break the habit of wrapping return values in parens. They are superfluous in that instance.

I actually do not know why I was wrapping return statements. Thanks for pointing that out.
Re: setter - that makes perfect sense. Step 6 in the project shows how to structure the getter method but not the setter method. So I inferred. I must have not paid attention in the setter lesson previous to the project.

1 Like

Thanks for the help. It resulted in better code. Here is my nice looking output: I would post the code but it would be a dead giveaway.

Courses:
Before adding appetizer dish
[ { name: 'nachos', price: '$6.00' },
  { name: 'stuffed mushrooms', price: '$7.50' },
  { name: 'green leaf salad', price: '$6.25' } ]

 After adding new appetizer.
[ { name: 'nachos', price: '$6.00' },
  { name: 'stuffed mushrooms', price: '$7.50' },
  { name: 'green leaf salad', price: '$6.25' },
  { name: 'Teriyaki PineApple Meatballs', price: '$7.75' } ]

Generating a random meal:
This is your meal: Appetizer: green leaf salad, Main: Dry-Rub Grilled Pork Chops over Cannellini Greens, Dessert: Peanut Butter Chocolate and the Total is $26.40
1 Like

You’re welcome; and, well done!

So it took me a lot of reading on the forums and experimenting to finally figure out an alternative to using Setter but basically here it is. Use the setters to push items into each respective array.

set appetizers(app) {
    this._courses.appetizers.push(app);
  },
  set mains(main) {
    this._courses.mains.push(main);
  },
  set desserts(dessert) {
     this._courses.desserts.push(dessert);
  },

Then when creating the addDishToCourse method you can use the setters to add the dishes in this manner:

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

Let me know if that makes sense.

This line in your code does not make sense to me.

this[courseName] = dish;

Since we are adding dishes to a course where course is an array of dish objects, I have: (you may have a different structure than I do)

 addDishToCourse(courseName, dishName, dishPrice) {
    //adds the object dish with properties name and price
    const dish = { name: dishName, price: dishPrice };
    return this._courses[courseName].push(dish); //adds dish to the appropriate course
  }

As the member admitted, ‘a lot of reading on the forums’ netted them the logic to use the setters. Since it likely came from yours truly, permit me to explain.

An assignment using a setter:

instance.prop = value

Within a method that has access to the context object (this),

this.prop = value

When the property name is referred by a variable we have to use subscript (bracket) syntax:

this[variable] = value

The setter is using .push() to append the course array.

Remember that setters are useful for making changes to properties you don’t wish to change directly.
In the setter methods I mentioned previously, I am associating each course name with the method of pushing the parameter into each respective array:
this._courses.desserts.push(dessert) for example
Therefore I can write something like menu.desserts = x or menu.desserts = {test: a, test: b} and the setter method will push whatever x is or {test:a, test: b} is into the array.
When this[courseName] = dish is executed it is essentially doing what menu.desserts = {test: a, test: b}.
Make sense?