Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion Guardfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
guard :minitest, bundler: false, rubygems: false do
guard :minitest, bundler: false, autorun: false, rubygems: false do
# with Minitest::Spec
watch(%r{^spec/(.*)_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
Expand Down
28 changes: 28 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
What classes does each implementation include? Are the lists the same?
Write down a sentence to describe each class.

The first implementation has a CartEntry class, a ShoppingCart class and an Order class with a total_price method. The second implementation has a price method in the CartEntry class that returns a sum based on unit price and quantity; a price method in the ShoppingCart class that collects the price for each entry and stores in variable named sum which will hold the price totals of all entries; there is a total price method in the Order class that takes the price of a ShoppingCart instance and stores into a variable called subtotal. This subtotal is added by itself and multiplied by a SALES_TAX to return a total for all items in cart.
----------
How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.

In the first implementation - To create an order instance, a ShoppingCart instance must also be created. They are tied together. This creates a coupling affect. The second implementation allows each class to calculate a sum. With the first class - the price of each item can be calculated based on its quantity. A shopping cart instance does not need to be created just to get the sum. There is also a price method that returns the sum of (the sum of all items). If one were to just want to see that price for an item based on its quantity, that is done entirely separate from the ShoppingCart class. Lastly there is a total price that DOES require information from another classes method to function. However a total price cannot be assessed without having a shopping cart thus this makes sense.
-----
What data does each class store? How (if at all) does this differ between the two implementations?
The second implementation's classes each have a method that calculates a sum. The first implementation - The order class stores dat of a shopping cart instance and calculates the price using the data from the CartEntry class.
-----
What methods does each class have? How (if at all) does this differ between the two implementations?
The first implementation has an instantiation and a total_price while while the second has a price method for each class except the Order class holds the totl price method. The second method removes dependencies on other classes.
-----
Consider the Order#total_price method. In each implementation:
Is logic to compute the price delegated to "lower level" classes like ShoppingCart and CartEntry, or is it retained in Order?
Does total_price directly manipulate the instance variables of other classes?
The first implementation delegates the computation through its dependency on lower level classes like ShoppingCart and CartEntry while the second implementation retains that computation within Order.
----
If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify? The second implementation seems better because you can assign prices per item based on quantity before placing it in a cart.
----
Which implementation better adheres to the single responsibility principle?
implementation B
----

Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled?
Once you've responded to the prompts, git add design-activity.md and git commit!
3 changes: 3 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def hotel
return "this is a hotel"
end
70 changes: 70 additions & 0 deletions lib/psuedocode
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
RESERVATION_MNGER

def list_rooms
returns array of all room instances
end

def find_rooms(room_number)
returns room instance that matches room_number
? call find_room instead?
end

def find_available_room(specific_date)
returns an instance of room that is available for a specific date
how do i know it's available?
ask all of the reservations "is this room under any reservations for some specific date?"
end

def reserve_room(room_number, start_date, end_date)
- takes room instance that matches room number
- make one new reservation for one room, for given start_date and end_date
- give the new reservation instance the room instance from step one
? - changes availability for a period of time
end

def list_reservations
- returns array of all reservation instances
end

def find_reservation(reservation_id)
- returns reservation instance that matches reservation id
? call find_reservation
end

def get_total(reservation_id)
- calculates each room and number of nights reserved
- returns total
end


ROOM

def current_status
- returns available or unavailable
end

def availability
- returns date range of when room is available
end

def cost(number_of_nights)
- returns cost * number of nights reserved
end

RESERVATION

def room_reserved
- what is the room associated with this reservation
- return room instance is associated with this reservation
end

def reservation_date
- returns date reservation begins and ends
- example: 02/02/2018 - 02/04/2018
- example: 2 days
? tricky/fuzzy/needs to be investigated: what data type is this going to be?
end

def total_room_cost
- calculates rooms_reserved * cost
end
20 changes: 20 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'time'
require 'date'

module Hotel
class Reservation
attr_accessor :room, :check_in, :check_out

def initialize(input)
@room = input[:room]
@check_in = Date.strptime(input[:check_in], '%m/%d/%Y')
@check_out = Date.strptime(input[:check_out], '%m/%d/%Y')
end

def room_reserved
return @room
end

end

end
96 changes: 96 additions & 0 deletions lib/reservation_mngr.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
require 'time'
require 'date'
require 'pry'


require_relative 'reservation'

module Hotel

class ReservationManager < Reservation

attr_reader :rooms, :reservations

def initialize
@rooms = build_room_list
@reservations = []
end

def build_room_list
rooms = []
20.times do |i|
rooms << Hotel::Room.new({room_number: "#{i + 1}".to_i, price: 200})
end
return rooms
end

def check_dates(check_in, check_out)
raise ArgumentError if check_out == nil
raise ArgumentError if check_in == nil
raise ArgumentError if check_out < check_in
raise ArgumentError if check_in > check_out
end

def find_room(check_in, check_out)
# find a way to use the find enumerable
# rm_avail = true
# @reservations.each do |reservation|
# if room.room_number == reservation.room.room_number
# if Date.strptime(check_in, '%m/%d/%Y') >= reservation.check_in && Date.strptime(check_out, '%m/%d/%Y') < reservation.check_out
# rm_avail = false
# break
# end
# else
# rm_avail = false
# end
# end
# if rm_avail
# return room
# end
check_in = Date.strptime(check_in, '%m/%d/%Y')
check_out = Date.strptime(check_out, '%m/%d/%Y')

unavailable = @reservations.collect do |reservation|
if check_in >= reservation.check_in && check_in < reservation.check_out
reservation.room
end
end
if unavailable.length == 20
return "No rooms available"
else
return @rooms[unavailable.length]
end
end


def create_reservation(check_in, check_out)
check_dates(check_in, check_out)
room = find_room(check_in, check_out)
reservation = Hotel::Reservation.new(room: room, check_in: check_in, check_out: check_out)


if reservation.room.room_number < 1 && reservation.room.room_number > 20
raise ArgumentError
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.

@reservations stores all of the reservations made in the whole system. Why does it throw an error if there are more than 20?

For example, what if I made 20 non-conflicting reservations for different dates? Should there be an error thrown when I made the 21st reservation?

@reservations << reservation
return reservation
end

def get_total(room, check_in, check_out)
@reservations.each do |reservation|
if reservation.room.nil? || reservation.room.room_number < 1 || reservation.room.room_number > 20
raise ArgumentError
elsif reservation.room.room_number == room
if check_in != reservation.check_in || check_out != reservation.check_out
raise ArgumentError
else
date = reservation.check_out - reservation.check_in
price = reservation.room.price
return price * date
end
end
end
end

end
end
22 changes: 22 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'time'

module Hotel

class Room
attr_accessor :room_number
attr_reader :price

def initialize(input)
@room_number = input[:room_number]
if @room_number < 1 || @room_number > 20
raise ArgumentError
end
@price = input[:price]
if @price != 200
raise ArgumentError
end
end

end

end
9 changes: 9 additions & 0 deletions spec/refactor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1. Move ArgumentErrors to check_dates method

2. Refactor find_rooms method - make a new method to minimize nested loops

3. Build rooms before creating reservation_mngr instances

4. Change name of "rez" in reservation_mngr test ln 64

5. Change name of "@rez" in reservation_mngr test ln 46
121 changes: 121 additions & 0 deletions spec/reservation_mngr_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require_relative 'spec_helper'

require 'date'

describe 'ReservationManager class' do

describe "ReservationManager instantiation" do
before do
@room = Hotel::Room.new( {room_number: 1, price: 200} )

@res_1 = Hotel::Reservation.new( { room: @room, check_in: "01/10/1988", check_out: "01/17/1988"} )

@front_desk = Hotel::ReservationManager.new()
end

it "is an instance of ReservationManager" do
expect(@front_desk).must_be_kind_of Hotel::ReservationManager
end

it "is set up for specific attributes and data types" do
[:rooms, :reservations].each do |prop|
expect(@front_desk).must_respond_to prop
end

expect(@front_desk.rooms).must_be_kind_of Array
expect(@front_desk.reservations).must_be_kind_of Array
end
end

describe "build_room_list" do
before do
@front_desk = Hotel::ReservationManager.new()
@room_list = @front_desk.build_room_list
end

it "returns an array length of 20" do
expect(@room_list.length).must_equal 20
end
end

describe "find_room" do
before do
@front_desk = Hotel::ReservationManager.new()
@room_list = @front_desk.build_room_list
@front_desk.find_room("01/03/2018", "01/10/2018")
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 method gets called, but it doesn't change anything and the return value doesn't get stored anywhere! Do we need this line?

end

it "returns a room that's available" do
res_1 = @front_desk.create_reservation("01/03/2018", "01/10/2018")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Even though the method create_reservation DOES call find_room within it, this test that is located in the describe block for "find_rooms method" doesn't call find_rooms in it... it'll be a better, more specific and targeted test if the test explicitly calls it.

expect(res_1.room.room_number).must_equal 1
end

it "returns next available room" do
@res_1 = @front_desk.create_reservation("01/03/2018", "01/10/2018")
@res_2 = @front_desk.create_reservation("01/03/2018", "01/07/2018")
expect(@res_2.room.room_number).must_equal 2
end

it "returns length of array when all rooms reserved" do
20.times do |i|
@front_desk.create_reservation("01/03/2018", "01/10/2018")
end
rez = @front_desk.reservations
expect(rez.length).must_equal 20
end

end


describe "create_reservation" do
before do
@room = Hotel::Room.new( {room_number: 1, price: 200} )
@front_desk = Hotel::ReservationManager.new()
end

it "throws an ArgumentError if check_out is before check_in" do
expect{@front_desk.create_reservation("01/10/2018", "01/09/2018")}.must_raise ArgumentError
end

it "throws an ArgumentError if check_in is after check_out" do
expect{@front_desk.create_reservation("01/18/1988", "01/17/1988")}.must_raise ArgumentError
end

it "throws an ArgumentError if check_in is nil" do
expect{@front_desk.create_reservation(nil, "01/17/1988")}.must_raise ArgumentError
end

it "throws an ArgumentError if check_out is nil" do
expect{@front_desk.create_reservation("01/18/1988", nil)}.must_raise ArgumentError
end

it "throws an ArgumentError if check_in and check_out are both nil" do
expect{@front_desk.create_reservation(nil, nil)}.must_raise ArgumentError
end

it "stores reservation instance to class variable - reservations" do
@front_desk.create_reservation("01/10/2018", "01/17/2018")
res = @front_desk.reservations.length
expect(res).must_equal 1
end

it "returns a reservation" do
expect(@front_desk.create_reservation("01/10/2018", "01/17/2018")).must_be_kind_of Hotel::Reservation
end
end

describe "get_total" do
before do
@front_desk = Hotel::ReservationManager.new()
@front_desk.create_reservation("01/10/1988", "01/17/1988")
end

it "calculates total cost of reservation" do
expect(@front_desk.get_total(1, Date.strptime("01/10/1988", '%m/%d/%Y'), Date.strptime("01/17/1988", '%m/%d/%Y') ) ).must_equal 1400

@front_desk.create_reservation("01/15/1988", "01/20/1988")

expect(@front_desk.get_total(2, Date.strptime("01/15/1988", '%m/%d/%Y'), Date.strptime("01/20/1988", '%m/%d/%Y') ) ).must_equal 1000
end
end
end
Loading