Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gawain Hewitt Takeaway challenge #2235

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

gawainhewitt
Copy link

Gawain Hewitt

Please write your full name here to make it easier to find your pull request.

User stories

Please list which user stories you've implemented (delete the ones that don't apply).

  • User story 1: "I would like to see a list of dishes with prices"
  • User story 2: "I would like to be able to select some number of several available dishes"
  • User story 3: "I would like to check that the total I have been given matches the sum of the various dishes in my order"

README checklist

My readme is very basic to be honest

Copy link

@archiemartini archiemartini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really like this, will look very nice in action

class Takeaway
attr_reader :menu
def initialize
@menu = Menu.new

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm impressed you definitely know what you're doing, especially with the corresponding tests

I'm no expert in dependency injection, but this article near the beginning

https://medium.com/@Bakku1505/introduction-to-dependency-injection-in-ruby-dc238655a278

explains how linking the classes together so "strongly" ie 'def initialize... @menu = Menu.new' can cause issues down the line

subject.show
end.to output("1. Chips - £1\n2. Tofu - £2\n3. Broccoli - £1\n4. Ice_cream - £2\n").to_stdout
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your general ruby syntax and string-morphing is fantastic!

expect(subject.menu).to receive(:show)
subject.show_menu
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, already thinking about testing injection (looking at commit 1) here is very switched on. nice. took a lot of research/cheating for me to come to tests like this

@@ -1,15 +1,31 @@
require 'takeaway'
require 'stringio'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll have to clue me in on this

@summary << order_item
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really impressive thought about actual user interface, certainly going beyond what is required. You have my sympathy and respect for keeping your head around it though

@dishes.each do |dish|
"food #{dish[:food]}"
if _dish == dish[:food]
if the_dish == dish[:food]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this could be simplified to a ternary operator

ie 'the_dish == dish[:food] ? true : false

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this method could also be renamed to something like contains_dish? so it's more explicit on what it does

Copy link

@leoht leoht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done, that's great work - I left some comments about a few different things to improve, but let me know if you'd like to discuss this feedback more in depth :)

end

def order
loop do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that you've worked with user input as well! I'd suggest looking at extracting further this logic into a new class, maybe named Cli or Interface, which would contain methods such as clarify_order or ask_for_order. It could probably also handle the display of the menu (which is right now in the Menu class). This way you can make the main Takeaway and Menu classes do a bit less, and it also makes it easier to test the input/output, as there will be only one class that directly uses puts or gets, so you remove the need to mock these for the other classes


context '#show' do
it 'should display menu' do
# output = <<~MENU
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reckon this didn't work because the heredoc syntax needs the "ending" tag (in your case MENU) to be on its own line, at the very beginning of the line (without any blank space before). This would make it:

it 'should display menu' do
  output = <<~MENU
       1. Chips - £1
       2. Tofu - £2
       3. Broccoli - £1
       4. Ice_cream - £2 
MENU

   # ...
end

end

def confirm_order
@summary.each do |dish|
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be part of the new class mentioned above - usually it's good practice to split the code that deals with "presenting" or display, from the code that is dealing with pure data or logic. This way, it's easier to change things related to how looks the program outputs (think formatting, translating, or more complex things!) without touching at the core logic of the program, which stays the same no matter how the output is presented and how the input is provided

end

def place_order_with_input(*order)
input = StringIO.new(order.join("\n") + "\n" + "\n" + "\n")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice way to mock IO!

@dishes.each do |dish|
"food #{dish[:food]}"
if _dish == dish[:food]
if the_dish == dish[:food]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this method could also be renamed to something like contains_dish? so it's more explicit on what it does

@input = input
@output = output
@dishes = [{ food: :Chips, price: 1 },
{ food: :Tofu, price: 2 }, { food: :Broccoli, price: 1 },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor one here - it's probably better to leave the dish names as strings rather than symbols, as symbols are mostly used for keys, special configuration values, enumerated values, etc, rather than purely "textual" values

describe 'Featuretest' do
context '#order' do
it 'will ask again if item mispelt' do
output = place_order_with_input("Brocoli", "Broccoli")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! This test suite should probably contain a bit more tests, at least one testing the whole integration of the different components with a successful order process, and assert the output of the takeaway.order method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants