In the spirit of learning Ruby, I wanted to share a challenge you can do to see if you know enough to say you know it. So here’s the rules.
1. You have 60 minutes to finish
2. You can use Google
That’s it. If you can finish all the deliverables, then congrats, you know Ruby!
Answer will be after the prompt
Prompt: You are building an app for a national bakery chain.
Models: Your models are the following: Bakery, Dessert, and Ingredients
- A Bakery has many desserts
- A Dessert belongs to a Bakery
- A Dessert has many Ingredients
- An Ingredient belongs to a Dessert
Write out the relationships using has_many, belongs_to and has_many_through.
Draw out the relationships!!! Create the necessary methods to connect these classes.
Bakery: When initializing a Bakery, it must have a name and a location. It can change its
name after it is initialized. It cannot change its location.
`#name`
— Should return the name of the Bakery instance
- `#location`
— Should return the location of the Bakery instance
- `#desserts`
— Should return an array of Dessert instances that this Bakery has made
- `#ingredients`
— Should return an array of Ingredient instances for the bakery’s desserts
- `#shopping_list`
— Should return a string of names for ingredients for the bakery
- `#average_calories`
— Should return a number totaling the average number of calories for the desserts sold at this bakery
Desserts: When initializing a Dessert, it must have a name and a calorie_count. It cannot change its name or calorie count after being initialized.
- `#name`
— Should return a string of the name for the Dessert instance
- `#ingredients`
— Should return an array of Ingredients for the dessert
- `#bakery`
— Should return the bakery object for the dessert
- `#calorie_count`
— Should return an integer of calorie count for the dessert
- `.all`
— should return an array of all desserts
Ingredients: When initializing an Ingredient, it must have a name. It cannot be changed after it’s initialized
- `#dessert`
— Should return a Dessert object for that ingredient
- `#bakery`
— Should return the Bakery object for the bakery that uses that ingredient
- `.all`
— Should return an array of all Ingredient instances
- `.find_all_by_name(ingredient_name)`
— should take a string argument and return an array of all ingredients that **include** that string in their name
— `.find_all_by_name(‘chocolate’)` might return `[‘chocolate sprinkles’, ‘chocolate mousse’, ‘chocolate’]`
— make sure you aren’t just looking for exact matches (like ‘chocolate’ == ‘chocolate’)
Good luck!
Answer
So first we’ll start with the Bakery
We need to have a Bakery class so we can start off with class Bakery
Being that we won’t be actually writing anything to the location (as the location can’t change) we’ll use attr_reader :location
.
The other values can use the accessor, so it should look like attr_accessor :name, :desserts, :ingredients
Then we need @@all = []
to create a new array of all
Initialize the variables with
def initialize(name, location)
@name, @location, @desserts = name, location, desserts @@all << self
end
or
def initialize(name, location)
@name = name
@location = location
@desserts = desserts @@all << self
end
They both do the same thing.
The rest of the code should look like this
def desserts
Dessert.all.select do |dessert|
dessert.bakery == self
end
enddef new_dessert(name, calories)
Dessert.new(name, calories)
enddef ingredients
desserts.map do |dessert|
dessert.ingredients
end
enddef average_calories
Bakery.desserts.all.inject(0) do |sum, dessert|
sum + desserts.calories
end / Bakery.desserts.all.count
end
So altogether, your Bakery class should look like:
class Bakeryattr_reader :location
attr_accessor :name, :desserts, :ingredients@@all = []def initialize(name, location)
@name, @location, @desserts = name, location, desserts @@all << self
enddef self.all
@@all
enddef desserts
Dessert.all.select do |dessert|
dessert.bakery == self
end
enddef new_dessert(name, calories)
Dessert.new(name, calories)
enddef ingredients
desserts.map do |dessert|
dessert.ingredients
end
enddef average_calories
Bakery.desserts.all.inject(0) do |sum, dessert|
# binding.pry
sum + desserts.calories
end / Bakery.desserts.all.count
endend
Dessert should look similar:
class Dessertattr_reader :name, :calories, :ingredients, :bakery@@all = []def initialize(name, calories, ingredients)
@name, @calories, @ingredients = name, calories, ingredients @@all << self
enddef self.all
@@all
enddef ingredientsIngredients.all.select do |ingredient|
ingredient.dessert
end
endend
And finally Ingredients should look like this:
class Ingredientattr_reader :name@@all = []def initialize(name)
@name = name @@all << self
enddef self.all
@@all
enddef dessert
Dessert.all.select do |dessert|
dessert.ingredients == self
end
enddef bakery
Bakery.all.select do |bakery|
bakery.ingedients == self
end
enddef self.find_all_by_name(ingredient)
Ingredient.all.include? (ingredient)
endend
You should notice that within the Bakery class and Dessert class that the shopping_list and ingredients methods are missing. That’s for you to work on!
Good luck!