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

Addie's Ride Share #25

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
67480f3
set up Rakefile and spec_helper
add2point71dots Mar 6, 2017
fc42834
set up initial file structure
add2point71dots Mar 6, 2017
5c4a935
sets up and tests initialize
add2point71dots Mar 6, 2017
ef9dfcc
Sets up and tests initialize for Rider
add2point71dots Mar 7, 2017
1296d00
Added .gitignore
add2point71dots Mar 7, 2017
3a81cc6
adds and tests initialize for Trip
add2point71dots Mar 7, 2017
8206e33
tinkering with require stuff
add2point71dots Mar 7, 2017
1a4ecf9
changed my befores to lets in tests and took out some comments in cla…
add2point71dots Mar 7, 2017
1b33663
raise argument errors for invalid information in initialize (and test…
add2point71dots Mar 7, 2017
fc16386
put everything in a RideShare module
add2point71dots Mar 7, 2017
2103dad
Adds and tests Driver.all method
add2point71dots Mar 7, 2017
1c1304d
Adds and tests Rider.all
add2point71dots Mar 7, 2017
ab077a6
Validates info when creating a new Rider (and tests that)
add2point71dots Mar 7, 2017
f050ae8
Put validation methods in RideShare module and cleaned up some code
add2point71dots Mar 7, 2017
70eaa87
Worked on Trip.all method and allowed IDs to be 0
add2point71dots Mar 8, 2017
739f891
Adds and tests Driver.find
add2point71dots Mar 8, 2017
bb68fdd
Adds and tests Rider.find method
add2point71dots Mar 8, 2017
5836a3d
working on the Trip.find_driver_trips
add2point71dots Mar 8, 2017
b7f3aa1
working on Trip.find_rider_trips method
add2point71dots Mar 8, 2017
4367649
Moved validation methods to separate module, plus some refactoring
add2point71dots Mar 8, 2017
cc7c8a9
made validation methods private
add2point71dots Mar 8, 2017
bfe2a6f
Adds and tests Driver.trips and messed with how classes are put in th…
add2point71dots Mar 8, 2017
b0df183
Adds and tests Driver.avg_rating
add2point71dots Mar 8, 2017
7742614
Adds and tests Rider.trips method
add2point71dots Mar 8, 2017
76184fb
require pry
add2point71dots Mar 8, 2017
d10b6d6
ignore a file I was playing around with
add2point71dots Mar 8, 2017
e2a21dd
Adds and tests Rider.drivers method
add2point71dots Mar 9, 2017
38a7b20
Added a comment for smthg to work on later
add2point71dots Mar 9, 2017
90e49a6
Adds and tests Trip.driver method
add2point71dots Mar 9, 2017
bc80463
Adds and tests Trip#rider method
add2point71dots Mar 9, 2017
475411c
put in some reminder comments
add2point71dots Mar 11, 2017
be92b35
Forces VINs to be 17 characters
add2point71dots Mar 11, 2017
817091b
changed validation of trip rating
add2point71dots Mar 12, 2017
a57f2bc
Added test for date input
add2point71dots Mar 13, 2017
11b6bfe
Minor formatting changes in test files
add2point71dots Mar 13, 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
coverage
test.rb
10 changes: 9 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
# Fill me in!
require 'rake/testtask'

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

task default: :test
Empty file removed lib/.keep
Empty file.
39 changes: 39 additions & 0 deletions lib/driver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module RideShare
class Driver
include Validation
attr_reader :id, :name, :vin

def initialize(driver_hash)
@id = validate_int(driver_hash[:id], "Driver ID")
@name = validate_string(driver_hash[:name], "Name")
@vin = validate_string_length(driver_hash[:vin], "VIN", 17)
end

def self.all
return CSV.read("support/drivers.csv")[1..-1].map do |line|
new( {
id: line[0].to_i,
name: line[1],
vin: line[2]
} )
end
end

def self.find(id)
found_driver = all.find { |driver| driver.id == id }
raise NoDriverError.new("Driver with that ID does not exist") if found_driver == nil
return found_driver
end

def trips
return Trip.find_driver_trips(id)
end

def avg_rating
raise NoRatingError.new("This driver doesn't have any ratings yet") if trips.empty?
trip_ratings = trips.map { |trip| trip.rating }
average_rating = trip_ratings.reduce(:+) / trips.length.to_f
return average_rating.round(2)
end
end
end
2 changes: 2 additions & 0 deletions lib/no_driver_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NoDriverError < StandardError
end
2 changes: 2 additions & 0 deletions lib/no_rating_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NoRatingError < StandardError
end
2 changes: 2 additions & 0 deletions lib/no_rider_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NoRiderError < StandardError
end
13 changes: 13 additions & 0 deletions lib/ride_share.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'csv'
require 'pry'

module RideShare
end

require_relative 'validation'
require_relative 'no_rider_error'
require_relative 'no_driver_error'
require_relative 'no_rating_error'
require_relative 'driver'
require_relative 'rider'
require_relative 'trip'
44 changes: 44 additions & 0 deletions lib/rider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module RideShare
class Rider
include Validation
attr_reader :id, :name, :phone

def initialize(rider_hash)
@id = validate_int(rider_hash[:id], "Rider ID")
@name = validate_string(rider_hash[:name], "Name")
@phone = validate_string(rider_hash[:phone], "Phone Number")
end

def self.all
return CSV.read("support/riders.csv")[1..-1].map do |line|
new( {
id: line[0].to_i,
name: line[1],
phone: line[2]
} )
end
end

def self.find(id)
found_rider = all.find { |rider| rider.id == id }
raise NoRiderError.new("Rider with that ID does not exist") if found_rider == nil
return found_rider
end

def trips
return Trip.find_rider_trips(id)
end

def drivers
drivers = trips.map do |trip|
begin
Driver.find(trip.driver_id)
rescue NoDriverError => e
puts "An error has occurred: #{e.message}"
end
end
drivers.delete(nil)
return drivers.uniq { |driver| driver.id }
end
end
end
52 changes: 52 additions & 0 deletions lib/trip.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module RideShare
class Trip
include Validation
attr_reader :id, :driver_id, :rider_id, :date, :rating

def initialize(trip_hash)
@id = validate_int(trip_hash[:id], "Trip ID")
@driver_id = validate_int(trip_hash[:driver_id], "Driver ID")
@rider_id = validate_int(trip_hash[:rider_id], "Rider ID")
@date = Date.parse(validate_string(trip_hash[:date], "Date"))
@rating = validate_int_range(trip_hash[:rating], "Rating", 1, 5)
end

def self.all
return CSV.read("support/trips.csv")[1..-1].map do |line|
new( {
id: line[0].to_i,
driver_id: line[1].to_i,
rider_id: line[2].to_i,
date: line[3],
rating: line[4].to_i
} )
end
end

def self.find_driver_trips(driver_id)
trips = all
return trips.select { |trip| driver_id == trip.driver_id }
end

def self.find_rider_trips(rider_id)
trips = all
return trips.select { |trip| rider_id == trip.rider_id }
end

def driver
begin
return Driver.find(driver_id)
rescue NoDriverError => e
puts "An error has occurred: #{e.message}"
end
end

def rider
begin
return Rider.find(rider_id)
rescue NoRiderError => e
puts "An error has occurred: #{e.message}"
end
end
end
end
29 changes: 29 additions & 0 deletions lib/validation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Validation
private

def validate_int(field, field_name)
if field.class != Integer || field < 0
raise ArgumentError.new("Required field #{field_name} must be a non-negative integer.")
end
return field
end

def validate_int_range(field, field_name, min, max)
valid_int = validate_int(field, field_name)
raise ArgumentError.new("#{field_name} must be between #{min} and #{max}") if !(valid_int.between?(min, max))
return valid_int
end

def validate_string(field, field_name)
if field.class != String || field == ""
raise ArgumentError.new("Required field #{field_name} must be a non-empty string.")
end
return field
end

def validate_string_length(field, field_name, length)
valid_string = validate_string(field, field_name)
raise ArgumentError.new("#{field_name} is invalid length") if valid_string.length != length
return valid_string
end
end
Empty file removed specs/.keep
Empty file.
144 changes: 144 additions & 0 deletions specs/driver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
require_relative 'spec_helper'

describe "Driver tests" do
let(:driver) { RideShare::Driver.new({ id: 4, name: "Ada", vin: "1XKAD49X2DJ395724" }) }
let(:drivers_array) { RideShare::Driver.all }
let(:csv_info) { CSV.read('support/drivers.csv')[1..-1] }
let (:driver64) { RideShare::Driver.find(64) }
let (:driver100) { RideShare::Driver.find(100) }

describe "Driver#initialize" do
it "Takes an ID, name, and VIN" do
driver.must_respond_to :id
driver.id.must_equal 4

driver.must_respond_to :name
driver.name.must_equal "Ada"

driver.must_respond_to :vin
driver.vin.must_equal "1XKAD49X2DJ395724"
end

it "Only accepts non-negative integer IDs" do
driver_hash1 = { id: "id", name: "Ada", vin: "1XKAD49X2DJ395724" }
driver_hash2 = { id: -5, name: "Ada", vin: "1XKAD49X2DJ395724" }

proc { RideShare::Driver.new(driver_hash1) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash2) }.must_raise ArgumentError
end

it "Only accepts non-empty strings for name" do
driver_hash1 = { id: 4, name: "", vin: "1XKAD49X2DJ395724" }
driver_hash2 = { id: 4, name: 45, vin: "1XKAD49X2DJ395724" }

proc { RideShare::Driver.new(driver_hash1) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash2) }.must_raise ArgumentError
end

it "Only accepts VINs that are strings of length 17" do
driver_hash1 = { id: 4, name: "Ada", vin: [] }
driver_hash2 = { id: 4, name: "Ada", vin: "" }
driver_hash3 = { id: 4, name: "Ada", vin: "1XKAD49X2DJ39572" }
driver_hash4 = { id: 4, name: "Ada", vin: "1XKAD49X2DJ3957246" }

proc { RideShare::Driver.new(driver_hash1) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash2) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash3) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash4) }.must_raise ArgumentError
end

it "All fields are required" do
driver_hash1 = { name: "Ada", vin: "1XKAD49X2DJ395724" }
driver_hash2 = { id: 4, vin: "1XKAD49X2DJ395724" }
driver_hash3 = { name: "Ada", id: 4}

proc { RideShare::Driver.new(driver_hash1) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash2) }.must_raise ArgumentError
proc { RideShare::Driver.new(driver_hash3) }.must_raise ArgumentError
end
end

describe "Driver.all" do
it "Driver.all returns an array" do
drivers_array.must_be_instance_of Array
end

it "First and last element in array is a Driver" do
drivers_array[0].must_be_instance_of RideShare::Driver
drivers_array[-1].must_be_instance_of RideShare::Driver
end

it "The number of drivers is correct" do
drivers_array.length.must_equal csv_info.count
end

it "The information for the first & last driver is correct" do
drivers_array[0].id.must_equal csv_info[0][0].to_i
drivers_array[0].name.must_equal csv_info[0][1]
drivers_array[0].vin.must_equal csv_info[0][2]

drivers_array[-1].id.must_equal csv_info[-1][0].to_i
drivers_array[-1].name.must_equal csv_info[-1][1]
drivers_array[-1].vin.must_equal csv_info[-1][2]
end
end

describe "Driver.find" do
it "Returns a driver that exists" do
RideShare::Driver.find(64).must_be_instance_of RideShare::Driver
RideShare::Driver.find(64).vin.must_equal "SUA9K8KA35CZ8X2FT"
end

it "Can find the first driver from the CSV" do
RideShare::Driver.find(csv_info[0][0].to_i).must_be_instance_of RideShare::Driver
RideShare::Driver.find(csv_info[0][0].to_i).name.must_equal csv_info[0][1]
end

it "Can find the last driver from the CSV" do
RideShare::Driver.find(csv_info[-1][0].to_i).must_be_instance_of RideShare::Driver
RideShare::Driver.find(csv_info[-1][0].to_i).vin.must_equal csv_info[-1][2]
end

it "Raises an error for a driver that doesn't exist" do
proc { RideShare::Driver.find(789078) }.must_raise NoDriverError
end
end

describe "Driver#trips" do
it "Returns an array" do
driver.trips.must_be_instance_of Array
end

it "First and last element of array are Trips" do
driver.trips[0].must_be_instance_of RideShare::Trip
driver.trips[-1].must_be_instance_of RideShare::Trip
end

it "The number of trips is correct" do
driver64.trips.length.must_equal 7
end

it "Returns an empty array if no trips are found" do
driver100.trips.must_equal []
end
end

describe "Driver#avg_rating" do
it "Returns correct rating for a driver" do
driver64.avg_rating.must_be_within_epsilon (19/7.0), 0.01
end

it "Must return a Float" do
driver64.avg_rating.must_be_instance_of Float
end

it "Raises error when there's no rating for a driver" do
proc { driver100.avg_rating }.must_raise NoRatingError
end

it "Returns rating with no more than two decimal places" do
rating_string = driver64.avg_rating.to_s
rating_string.length.must_be :<=, 4
end
end
end
Loading