Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**/.DS_Store
/coverage

.env
# Local cache of Rubocop remote config
.rubocop-*
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ end

group :development, :test do
gem 'rubocop', '1.20'
gem 'twilio-ruby'
gem 'dotenv'
end
93 changes: 92 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,93 @@
GEM
remote: https://rubygems.org/
specs:
actionpack (7.0.2.4)
actionview (= 7.0.2.4)
activesupport (= 7.0.2.4)
rack (~> 2.0, >= 2.2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (7.0.2.4)
activesupport (= 7.0.2.4)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activesupport (7.0.2.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
ansi (1.5.0)
ast (2.4.2)
builder (3.2.4)
concurrent-ruby (1.1.10)
crass (1.0.6)
diff-lcs (1.4.4)
docile (1.4.0)
dotenv (2.7.6)
dotenv-rails (2.7.6)
dotenv (= 2.7.6)
railties (>= 3.2)
erubi (1.10.0)
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
jwt (2.3.0)
loofah (2.17.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
method_source (1.0.0)
mini_portile2 (2.8.0)
minitest (5.15.0)
multipart-post (2.1.1)
nokogiri (1.13.4)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
parallel (1.20.1)
parser (3.0.2.0)
ast (~> 2.4.1)
racc (1.6.0)
rack (2.2.3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.2)
loofah (~> 2.3)
railties (7.0.2.4)
actionpack (= 7.0.2.4)
activesupport (= 7.0.2.4)
method_source
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rainbow (3.0.0)
rake (13.0.6)
regexp_parser (2.1.1)
rexml (3.2.5)
rspec (3.10.0)
Expand Down Expand Up @@ -36,6 +115,7 @@ GEM
rubocop-ast (1.11.0)
parser (>= 3.0.1.1)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.5)
simplecov (0.21.2)
docile (~> 1.1)
simplecov-html (~> 0.11)
Expand All @@ -48,19 +128,30 @@ GEM
simplecov_json_formatter (0.1.3)
terminal-table (3.0.1)
unicode-display_width (>= 1.1.1, < 3)
thor (1.2.1)
twilio-ruby (5.66.2)
faraday (>= 0.9, < 2.0)
jwt (>= 1.5, <= 2.5)
nokogiri (>= 1.6, < 2.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
unicode-display_width (2.0.0)
zeitwerk (2.5.4)

PLATFORMS
ruby

DEPENDENCIES
dotenv
dotenv-rails
rspec
rubocop (= 1.20)
simplecov
simplecov-console
twilio-ruby

RUBY VERSION
ruby 3.0.2p107

BUNDLED WITH
2.2.26
2.3.12
24 changes: 24 additions & 0 deletions lib/confirmation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'twilio-ruby'
require 'dotenv'
Dotenv.load

class Confirmation

def initialize
@to = ENV['TO_PHONE_NUMBER']
from = ENV['TWILIO_PHONE_NUMBER']
end

def send
account_sid = ENV['TWILIO_ACCOUNT_SID']
auth_token = ENV['TWILIO_AUTH_TOKEN']
client = Twilio::REST::Client.new(account_sid, auth_token)

client.messages.create(
from: from,
to: @to,
body: "Thank you for your order"
)
end

end
26 changes: 26 additions & 0 deletions lib/menu.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Menu

attr_reader :menu

def initialize
@menu = [
{ :item => 1, :dish => "Mattar Paneer", :price => 12.50 },
{ :item => 2, :dish => "Black Daal", :price => 7.50 },
{ :item => 3, :dish => "Raita", :price => 3.50 },
{ :item => 4, :dish => "Garlic Naan", :price => 3.50 }
]
end

@eoinmakers eoinmakers May 6, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hashes are most useful where you have a key value pair - eg. if the only information you needed to record was the item name and price, a simple hash could look like:

@menu = { "1. Mattar Paneer" => 12.50, "Black Daal" => 7.50 }

@menu[item_name] will return the cost of that item.

For data requiring more than two values, where key/value isn't enough, I would suggest defining a new object, for example:

class Dish
    def initialize(name, price)
        @name = name
        @price = price
    end

    # getter methods for retrieving information
end

This way, you could work with an array of Dishes inside your Menu class, eg. @menu = [Dish.new(args), Dish.new(args), etc.]

Singular dish data can be accessed with @menu[0].name, etc. Which can be quite a bit easier than traversing a complex hash!


def view
@menu.map { |dish| "#{dish[:item]}. #{dish[:dish]} £#{dish[:price]}" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Were you to use just a single key/value hash as the one I suggested in my first comment, you could refactor this to something like:

puts "#{key}:#{value}"

This will print the full menu.

end

def existing_dish(number, qty)
@menu.select { |dish| dish[:item] == number } != []
end

def selection(number, qty)
@menu.select { |dish| dish[:item] == number }
end

end
14 changes: 14 additions & 0 deletions lib/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Order

DELIVERY = 2700

def initialize(time = Time.new)
@time = time
end

def delivery_time
duration = @time + DELIVERY
duration.strftime("%H:%M")
end

end
68 changes: 68 additions & 0 deletions lib/take_away.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
class TakeAway

attr_reader :menu, :order, :take_away

def initialize(menu = Menu.new, confirmation = Confirmation.new)
@confirmation = confirmation
@menu = menu
@order = []
@take_away = 0
@total = 0
@current_dish = []
end

def view_menu
@menu.view
end

def add_dish(number, qty)
fail "please enter a valid dish number" if @menu.existing_dish(number, qty) != true
if duplicate_dish(number, qty) == true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This seems like a good idea. I just kept adding to the 'basket' array of hashes, so your idea of actually editing a quantity value seems a lot more like a real user experience

update_qty(number, qty)
else
@order << current_dish(number, qty)
end
dish_added_message(number, qty)
end

def view_basket
@order.map { |dish| "#{dish[:qty]} x #{dish[:dish]} £#{dish[:price]}/each -> £#{dish[:subtotal]}" }
end

def order_total
"Your order total is £#{total}"
end

def place_order
@confirmation.send
end

private

def duplicate_dish(number, qty)
@order.select { |dish| dish[:item] == number } != []
end

def update_qty(number, qty)
@order.map { |dish| (dish[:qty] = (dish[:qty] + qty)) && (dish[:subtotal] = dish[:qty] * dish[:price]) if (dish[:item] == number) }
end

def current_dish(number, qty)
(@menu.selection(number, qty).push(:qty => qty, :subtotal => sub_total(number, qty))).reduce(&:merge)
end

def dish_added_message(number, qty)
(@menu.selection(number, qty)).map do |dish|
"#{qty} x #{dish[:dish]} £#{dish[:price]}/each, has been added to your order -> £#{(sub_total(number, qty))}"
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Although this is functional, the functionality to receive a confirmation for each item added to the order is not mentioned in the spec - you should stick as closely as possible to the spec as possible. This helps keep your code clean / simple!

end

def sub_total(number, qty)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You could omit this and only calculate the total at runtime / when the user confirms the order.

sub_total = @menu.selection(number, qty)
sub_total.map { |item| item[:price] * qty }
end

def total
@order.map { |item| (item[:subtotal]) }.flatten.sum
end
end
11 changes: 11 additions & 0 deletions spec/confirmation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'confirmation'

describe Confirmation do

subject(:confirmation) { Confirmation.new }

it "should create an instance of class Confirmation" do
expect(confirmation).to be_instance_of(Confirmation)
end

end
29 changes: 29 additions & 0 deletions spec/menu_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'menu'

describe Menu do

subject(:menu) { Menu.new }

it "should create an instance of class Menu" do
expect(menu).to be_instance_of(Menu)
end

describe "#view" do
it "should show menu options" do
expect(menu.view).to eq(["1. Mattar Paneer £12.5", "2. Black Daal £7.5", "3. Raita £3.5", "4. Garlic Naan £3.5"])
end
end

describe "#existing_dish" do
it "should return false if entered item is not part of menu" do
expect(menu.existing_dish(14, 1)).to eq(false)
end
end

describe "#selection" do
it "should filter the menu for the selected dish and return it" do
expect(menu.selection(2, 1)).to eq([{ :item => 2, :dish => "Black Daal", :price => 7.5 }])
end
end

end
11 changes: 11 additions & 0 deletions spec/order_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'order'

describe Order do

subject(:order) { Order.new }

it "should create an instance of class Order" do
expect(order).to be_instance_of(Order)
end

end
Loading