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
51 changes: 51 additions & 0 deletions lib/account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Update the Account class to be able to handle all of these fields from the CSV file used as input.
# For example, manually choose the data from the first line of the CSV file and ensure you can create a new instance of your Account using that data

require 'csv'


module Bank
class Account
attr_accessor :id, :balance, :date_created

Choose a reason for hiding this comment

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

Should these be attr_accessor? Seems to me that attr_reader would be more appropriate - you don't want people trying to modify @balance directly, they should go through withdraw or deposit instead.

def initialize(id, balance, date_created = nil)
raise ArgumentError.new("balance must be >= 0") if balance < 0
@id = id
@balance = balance
@date_created = date_created

end

def self.all
@accounts = []
CSV.open("./support/accounts.csv").each do |line|
@accounts << self.new(line[0].to_i, line[1].to_f, line[2].to_s)
end
return @accounts
end

def self.find(id)
account_find = Bank::Account.all
account_find.each do |account|
if account.id == id
return account
end
end
raise ArgumentError.new "Account #{id} doesn't exist, sorry"
end

def withdraw(amount)
raise ArgumentError.new("amount must be >= 0") if amount < 0
if @balance - amount < 0
puts "Balance cannot be negative"
return @balance
else
return @balance -= amount
end
end

def deposit(amount)
raise ArgumentError.new("amount must be >= 0") if amount < 0
return @balance += amount
end
end
end
42 changes: 42 additions & 0 deletions lib/checking_account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require_relative 'account'

module Bank
class CheckingAccount< Account
attr_accessor :id, :balance

Choose a reason for hiding this comment

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

Turns out the attr_accessor methods are one of the things we get for free via inheritance, so this line is not needed.


def initialize(id, balance)
super(id, balance)
@check_count = 0
@fee = 2
raise ArgumentError.new("balance must be >= -1-") if balance < 10
end

def withdraw(amount)
if amount < (@balance - 11)

Choose a reason for hiding this comment

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

Would it be possible to refactor your withdraw methods so that the versions in the subclasses could take advantage of Account.withdraw? You might need to add some extra information about fees or minimum balances, but it has the potential to make the code much DRYer.

It looks like you may have been headed way with the @fee instance variable, but I don't think it ever gets used.

puts "Outputs a warning if the balance would go below $10"
return @balance -= (amount + 1)
else
return @balance
end
end

def withdraw_using_check(amount)
raise ArgumentError.new("Invalid amount, try again.") if amount < 0

if (@check_count < 3) && (@balance - amount) >= -10
@check_count += 1
@balance -= amount
elsif (@check_count >= 3) && (@balance - amount) >= -12
@balance -= (amount + 2)
else
puts "Sorry, can't go below -$10"
end
return @balance
end

def reset_checks
@check_count = 0
end
end

end
32 changes: 32 additions & 0 deletions lib/savings_account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require_relative 'account'

module Bank
class SavingsAccount < Account
attr_accessor :id, :balance

def initialize(id, balance)
super(id, balance)

raise ArgumentError.new("balance must be >= 10") if balance < 10

end

def withdraw(amount)
raise ArgumentError.new("amount must be >= 0") if amount < 0
if amount < (@balance - 12)
puts "Outputs a warning if the balance would go below $10"
return @balance -= (amount + 2)
else
return @balance
end
end

def add_interest(rate)
raise ArgumentError.new("interest rate must be >= 0") if rate < 0
interest_calculation = (@balance * (rate/100))
@balance += interest_calculation
return interest_calculation
end

end
end
75 changes: 45 additions & 30 deletions specs/account_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,29 @@

describe "Wave 1" do
describe "Account#initialize" do
it "Takes an ID and an initial balance" do
it "Takes an ID, an initial balance, and date created" do
id = 1337
balance = 100.0

account = Bank::Account.new(id, balance)

account.must_respond_to :id
account.id.must_equal id

account.must_respond_to :balance
account.balance.must_equal balance

end

it "Raises an ArgumentError when created with a negative balance" do
# Note: we haven't talked about procs yet. You can think
# of them like blocks that sit by themselves.
# This code checks that, when the proc is executed, it
# raises an ArgumentError.

proc {
Bank::Account.new(1337, -100.0)
}.must_raise ArgumentError
end

it "Can be created with a balance of 0" do
# If this raises, the test will fail. No 'must's needed!

Bank::Account.new(1337, 0)
end
end
Expand Down Expand Up @@ -61,13 +60,10 @@
withdrawal_amount = 200.0
account = Bank::Account.new(1337, start_balance)

# Another proc! This test expects something to be printed
# to the terminal, using 'must_output'. /.+/ is a regular
# expression matching one or more characters - as long as
# anything at all is printed out the test will pass.

proc {
account.withdraw(withdrawal_amount)
}.must_output /.+/
}.must_output(/.+/)
end

it "Doesn't modify the balance if the account would go negative" do
Expand All @@ -77,8 +73,6 @@

updated_balance = account.withdraw(withdrawal_amount)

# Both the value returned and the balance in the account
# must be un-modified.
updated_balance.must_equal start_balance
account.balance.must_equal start_balance
end
Expand Down Expand Up @@ -124,7 +118,7 @@
updated_balance.must_equal expected_balance
end

it "Requires a positive deposit amount" do
it "Requires a positive deposit amount" do
start_balance = 100.0
deposit_amount = -25.0
account = Bank::Account.new(1337, start_balance)
Expand All @@ -136,36 +130,57 @@
end
end

# TODO: change 'xdescribe' to 'describe' to run these tests
xdescribe "Wave 2" do
describe "Wave 2" do
describe "Account.all" do
it "Returns an array of all accounts" do
# TODO: Your test code here!
# Useful checks might include:
# - Account.all returns an array
# - Everything in the array is an Account
# - The number of accounts is correct
# - The ID and balance of the first and last
# accounts match what's in the CSV file
# Feel free to split this into multiple tests if needed
before do
@spec_accounts = Bank::Account.all
end
it "Accounts.all returns an array" do
@spec_accounts.class.must_equal Array, "This is not an array"
end

it "Everything in the array is an Account" do
@spec_accounts.each do |account|
account.must_be_instance_of Bank::Account
end
end

it "The number of accounts is correct" do
@spec_accounts.length.must_equal 12
end

it "The ID and balance of the first and last accounts match" do
@spec_accounts[0].id.must_equal 1212, "Oops this should match the id, but it doesn't"
@spec_accounts[0].balance.must_equal 1235667, "Rurow, this should match the balance, but it doesn't"

@spec_accounts[11].id.must_equal 15156, "Oops this should match the id, but it doesn't"
@spec_accounts[11].balance.must_equal 4356772, "Rurow, this should match the balance, but it doesn't"
end
end
end

describe "Account.find" do
it "Returns an account that exists" do
# TODO: Your test code here!
sample_account = Bank::Account.find(1212)
sample_account.must_be_instance_of Bank::Account
sample_account.id.must_equal 1212
end

it "Can find the first account from the CSV" do
# TODO: Your test code here!
first_account = Bank::Account.find(1212)
first_account.must_be_instance_of Bank::Account
first_account.id.must_equal 1212
end

it "Can find the last account from the CSV" do
# TODO: Your test code here!
last_account = Bank::Account.find(15156)
last_account.must_be_instance_of Bank::Account
last_account.id.must_equal 15156
end

it "Raises an error for an account that doesn't exist" do
# TODO: Your test code here!
proc {
Bank::Account.find(12345678)
}.must_raise ArgumentError
end
end
end
Loading