Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
355958e
forgot to commit when files were created
Sep 6, 2017
3290eb5
forgot to commit again, created tests for Reservation, Room, DateRange
Sep 7, 2017
096475f
changed ROOMS to rooms_available
Sep 7, 2017
0506643
create test 'removes unavailable rooms'
Sep 7, 2017
737ea0d
pass test 'remove checked in room from array'
Sep 7, 2017
fbc86ef
prep for room assign
Sep 8, 2017
7a3cc13
commenting a big question because i am confused
Sep 8, 2017
4b73c40
@@rooms_available, diff room for diff guests
Sep 8, 2017
2b1b0c3
remove room as booked/fail assign diff room
Sep 8, 2017
7110fa2
change rooms_available to ROOMS
Sep 8, 2017
c0fbf2e
@puppy_room @kitten_room @bat_room
Sep 8, 2017
f3b4d4f
rooms are returned to the array at checkout
Sep 8, 2017
8c8d24e
returns rooms to array in numerical order
Sep 8, 2017
bf1b1aa
begin working on dates
Sep 8, 2017
4b442a8
try making reservation hash
Sep 8, 2017
ca5e582
create mad hash for reservation
Sep 8, 2017
a2224f9
grammar
Sep 8, 2017
544b227
reservation info output - fails
Sep 8, 2017
68cb68d
pass print reservation info
Sep 8, 2017
205a157
start hash
Sep 10, 2017
efee7b2
create hash of booking info
Sep 10, 2017
19270be
self.list_all mess
Sep 10, 2017
f5e776a
pass print_list
Sep 10, 2017
0e6a2a4
list reservations on a given date
Sep 10, 2017
5397ce1
test self.reservations
Sep 11, 2017
acc4c64
begin #available? tests
Sep 11, 2017
4819f44
self.available_rooms and rooms.csv
Sep 11, 2017
a6eb6b3
self.all self.find spec pass
Sep 11, 2017
0d1b5d3
cannot book already booked room
Sep 11, 2017
c12430c
answer most of design activity questions
Sep 28, 2017
b732072
move logic from reservation to daterange, add test to init in daterang
Sep 29, 2017
bf25ae6
add custom errors to daterange and room classes
Sep 29, 2017
55a62ee
update spec_helper, add hotel class
Sep 29, 2017
7a3dfc4
answer activity question
Oct 1, 2017
13922bf
methods number_of_nights, total_cost
Oct 1, 2017
0170e45
comment out all of room.rb
Oct 2, 2017
bf1daaa
create and pass tests for reservation_spec
Oct 2, 2017
31f6a4c
date_range_spec initialize tests pass
Oct 2, 2017
47eaf1d
move extraneous methods from reservation to hotel
Oct 2, 2017
69f5f63
pretty_print, list reservations, list by date, list all date_range_sp…
Oct 2, 2017
90976dc
pass the 'true' overlap tests in date_range_spec
Oct 2, 2017
7103fa4
pass date_range_spec overlap tests
Oct 2, 2017
8b0b452
finish all tests and questions
Oct 2, 2017
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
9 changes: 9 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'rake/testtask'

Rake::TestTask.new do |t|
t.libs = []
t.warning = true
t.test_files = FileList['./specs/*_spec.rb']
end

task default: :test
34 changes: 34 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
What classes does each implementation include? Are the lists the same?
A: CartEntry, ShoppingCart, Order
B: CartEntry, ShoppingCart, Order
(The same!)

Write down a sentence to describe each class.
CartEntry: In both implementations, it collects the unit price and quantity. B will also find the price by multiplying the two arguments passed in.
ShoppingCart: Both create an array of items in the cart. In B, I _think_ it is trying to iterate through the entries array and add the price of each item in the cart to sum (it is unclear where entry.price is coming from, but I assume from CartEntry.price?)
Order: Each implementation finds the total price of the order, including tax. A does it by iterating through the entries array and adding each item with its own tax to a total price, whereas B adds tax to the final subtotal.

How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.
CartEntry collects info of an item placed in the cart > ShoppingCart stores each entry into an array > Order calculates the total cost of items in the array, plus tax.

What data does each class store? How (if at all) does this differ between the two implementations?
@unit_price, @quantity, @entries, @cart. They all seem the same to me--initialized the same and seem to hold the same information.

What methods does each class have? How (if at all) does this differ between the two implementations?
Each class has an initialize method. Both Order classes have a total_price method. implementation B has an additional price method for its CartEntry and ShoppingCart 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?
implementation A does not--it retains all logic in itself, and only uses values from other classes. B does, using ShoppingCart#price.

Does total_price directly manipulate the instance variables of other classes?
No. They both use the values in local variables.

If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify?
I feel like A would be easier to modify because it calculates the price only once, and it would be simpler to make changes in one class than the several classes it would be in B.

Which implementation better adheres to the single responsibility principle?
A. A keeps all of its pricing math within the Order class, whereas B calculates price in some way in each of its classes.

Identify one place in your Hotel project where a class takes on multiple roles, or directly modifies the attributes of another class.
My Reservation class should only be responsible for a single reservation. Instead of Reservation creating AND storing every instance, I should have a Hotel class to store all reservations in. That would make it much easier to create a Blocks class, which I was unable to do when the project was originally assigned.
23 changes: 23 additions & 0 deletions lib/date_range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Hotel
class DateRange
class InvalidDateRange < StandardError ; end
attr_reader :check_in, :check_out

def initialize(check_in, check_out)
unless check_out > check_in
raise InvalidDateRange.new("Invalid dates #{check_in} to #{check_out}") # I took this from the example--I wouldn't have thought to put this here and it is such a good idea
end

@check_in = check_in
@check_out = check_out
end # end initialize

def number_of_nights
return @check_out - @check_in
end # end number_of_nights

def overlap?(other)
!(@check_out <= other.check_in || @check_in >= other.check_out)
end # end overlap?
end # end of class
end # end of module
48 changes: 48 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

module Hotel
class Hotel
class InvalidRoomError < StandardError ; end
attr_reader :reservations, :rooms

def initialize
@reservations = []
@rooms = (1..20).to_a
end # initialize

def available_rooms(date_range)
reservations = @reservations.reject do |reservation| # removes rooms already booked
!reservation.dates.overlap?(date_range)
end
reserved_rooms = reservations.map do |reservation| # converts each reservation in reservations into its room number
reservation.room
end
return @rooms.reject do |room| # returns the available room numbers by removing reserved rooms from the @rooms list
reserved_rooms.include?(room)
end
end # end available_rooms

def add_reservation(reservation)
available = available_rooms(reservation.dates)
if !available.include?(reservation.room)
raise InvalidRoomError.new('This room has already been booked') # tests if room has already been booked
else
@reservations << reservation
end
end # end add_reservation

def all_reservations
return @reservations.map do |reservation|
reservation.pretty_print
end
end # end all_reservations

def list_on_date(date)
reservations = @reservations.select do |reservation|
reservation.dates.check_in <= date && date <= reservation.dates.check_out
end
return reservations.map do |reservation|
reservation.pretty_print
end
end # end on_date
end # end class
end # end module
61 changes: 61 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require_relative 'date_range'
module Hotel
class Reservation # various ways to list reservations
# COST = 200 # per night
# @@reservations = [] # list of all reservations made
attr_reader :dates, :room, :rate

def initialize(dates, room, rate)
@dates = dates
@room = room
@rate = 200
# available_room_numbers = Hotel::Reservation.available_rooms(@dates).map do |room|
# room.room_number
# end
# if !available_room_numbers.include?(@room.room_number)
# raise InvalidRoomError.new('This room has already been booked')
# end # tests if room has already been booked, raises error if so
# @@reservations << self # each new instance put into the list of total reservations
end # end initialize

def final_cost
return @rate * @dates.number_of_nights.to_i
end # end final_cost

def pretty_print
return "Check In: #{@dates.check_in}\nCheck Out: #{@dates.check_out}\nRoom Number: #{@room}\nTotal Cost: $#{final_cost}"
end

# def self.reservations
# @@reservations
# end # end self.reservations

# def self.print_list
# bookings = []
# @@reservations.each do |booking|
# bookings << "Check In: #{booking.check_in}\nCheck Out: #{booking.check_out}\nRoom Number: #{booking.room.room_number}\nTotal Cost: $#{booking.cost}" # turns out you can't use instance variables within a class method
# end
# return bookings
# end # end self.print_list

# def self.on_date(date) # list reservations on a given date
# @@reservations.select do |reservation|
# reservation.check_in == date
# end
# end # end self.on_date
#
# def self.available_rooms(date_range) # list reservations on given date range
# reservations_in_range = @@reservations.reject do |reservation| # excludes reservastions outside date range
# reservation.dates.overlap?(date_range)
# end
#
# rooms_in_range = reservations_in_range.map do |reservation| # iterates over reservations_in_range and converts each reservation into its room number (instead of list of obj, becomes list of int)
# reservation.room.room_number
# end
#
# return Hotel::Room.all.reject do |room| # remove from list of rooms without reservations in date range
# rooms_in_range.include?(room.room_number)
# end
# end # end self.available_rooms
end # end of Reservation
end # end of Hotel module
34 changes: 34 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#################################
# decided I don't need this class
#################################

# require 'spec_helper'
#
# module Hotel
# class Room
# class InvalidRoomNumber < StandardError ; end
# attr_reader :room_number, :rooms_available
#
# def initialize(room_number)
# @room_number = room_number
# end # end initialize
#
# def self.all
# all_rooms = []
# CSV.open("support/rooms.csv", 'r').each do |line|
# room_number = line[0].to_i
# all_rooms << self.new(room_number)
# end
# return all_rooms
# end # end self.all
#
# def self.find(room_number)
# self.all.each do |room|
# if room_number == room.room_number
# return room
# end
# end
# raise InvalidRoomNumber.new ('Invalid Room Number')
# end # end self.find
# end # end Room class
# end # Hotel module
138 changes: 138 additions & 0 deletions specs/date_range_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
require_relative 'spec_helper'

describe 'DateRange' do

describe 'initialize' do
it 'passes in two Date objects as check in and check out arguments' do
check_in = Date.new(2017, 10, 13)
check_out = Date.new(2017, 10, 31)
honeymoon = Hotel::DateRange.new(check_in, check_out)

honeymoon.check_in.must_be_kind_of Date
honeymoon.check_out.must_be_kind_of Date
end

it 'cannot have a negative number of nights' do
check_out = Date.new(2017, 10, 13)
check_in = Date.new(2017, 10, 31)

proc { Hotel::DateRange.new(check_in, check_out) }.must_raise Hotel::DateRange::InvalidDateRange
end

it 'cannot book zero nights' do
check_out = Date.new(2017, 10, 13)
check_in = Date.new(2017, 10, 13)

proc { Hotel::DateRange.new(check_in, check_out) }.must_raise Hotel::DateRange::InvalidDateRange
end
end # end initialize

describe 'number_of_nights' do
it 'returns the number of nights passed in' do
check_in = Date.new(2017, 10, 13)
check_out = Date.new(2017, 10, 31)
honeymoon = Hotel::DateRange.new(check_in, check_out)

honeymoon.number_of_nights.must_equal 18
end
end # end number_of_nights

describe 'overlap?' do
before do
@check_in = Date.new(2017, 10, 13)
@check_out = Date.new(2017, 10, 31)
@honeymoon = Hotel::DateRange.new(@check_in, @check_out)
end

it 'returns true if the check in dates are the same' do
birthday = Hotel::DateRange.new(@check_in, @check_out)
@honeymoon.overlap?(birthday).must_equal true
end

it 'returns true if the reservation starts before the other ends' do
check_in = Date.new(2017, 10, 10)
check_out = Date.new(2017, 10, 15)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal true
end

it 'returns true if the reservation ends after the other starts' do
check_in = Date.new(2017, 10, 30)
check_out = Date.new(2017, 11, 1)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal true
end

it 'returns true if the new date range is contained in the other date range' do
check_in = Date.new(2017, 10, 15)
check_out = Date.new(2017, 10, 16)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal true
end

it 'returns true if the new date range contains the other date range' do
check_in = Date.new(2017, 10, 1)
check_out = Date.new(2017, 11, 1)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal true
end

it 'returns false if the reservation ends before the other starts' do
check_in = Date.new(2017, 10, 1)
check_out = Date.new(2017, 10, 12)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal false
end

it 'returns false if the reservation begins after the other ends' do
check_in = Date.new(2017, 11, 1)
check_out = Date.new(2017, 11, 2)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal false
end

it 'returns false if the reservation begins on the other check out date' do
check_in = Date.new(2017, 10, 1)
check_out = Date.new(2017, 10, 13)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal false
end

it 'returns false if the reservation ends on the other check in date' do
check_in = Date.new(2017, 10, 31)
check_out = Date.new(2017, 11, 1)
birthday = Hotel::DateRange.new(check_in, check_out)

@honeymoon.overlap?(birthday).must_equal false
end
end # end overlap?

# before do
# @puppy_dates = Hotel::DateRange.new(Date.new(2017, 10, 13), Date.new(2017, 10, 31))
# end # end before
#
# describe 'initialize' do
# it 'takes a check in date and a check out date' do
# @puppy_dates.check_in.to_s.must_equal '2017-10-13'
# @puppy_dates.check_out.to_s.must_equal '2017-10-31'
# end # end test
#
# it 'passes check_in and check_out in as Date objects' do
# @puppy_dates.check_in.class.must_equal Date
# @puppy_dates.check_out.class.must_equal Date
# end # end test
# end # end #initialize
#
# describe 'length_of_stay' do
# it 'finds the number of days needed for the reservation based on given dates' do
# @puppy_dates.length_of_stay.must_equal 18
# end # end test
# end # end #length_of_stay
end # end of all DateRange tests
Loading