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
47 changes: 47 additions & 0 deletions lib/account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'csv'
require 'time'

module Bank
class Account
attr_reader :id, :balance, :date
def initialize(id, balance, date="nil")
@id = id
@balance = balance
@date = date
raise ArgumentError.new("balance must be >= 0") if balance < 0
end

def self.find(id1)
@accounts_array.each do |line|

Choose a reason for hiding this comment

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

I like the idea of using the accounts loaded in Account.all here in find. But there's a problem - if find is run before all, you get an error! How could you guarantee that all has been run by the time you get here?

return line if line.id == id1
raise ArgumentError.new("no valid id") if line.id != id1
end
end

def self.all
@accounts_array = []

Choose a reason for hiding this comment

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

You probably want a class variable (two @s) here. What you'v got is an instance variable defined at the class level, which can act a little weird in some situations. Better to just stick with the class variable, at least for now.

#I had to use this whole branch because it was the only way it worked
#Wierd!
#A little out the line of good style. Sorry
CSV.open("/Users/laurams/ada/homework/BankAccounts/support/accounts.csv").each do |line|
@accounts_array << self.new(line[0].to_i, line[1].to_i, Time.parse(line[2]))
end
@accounts_array
end

def withdraw(withdraw_amount)
raise ArgumentError.new("Unvalid amount!") if withdraw_amount < 0
if (@balance - withdraw_amount) <0
print "warning! Your balance is #{@balance}"
return @balance
end

return @balance if (@balance -= withdraw_amount) >= 0
end

def deposit(amount)
raise ArgumentError.new("Can't deposit negative money") if amount < 0
@balance += amount
end
end
end
38 changes: 38 additions & 0 deletions lib/checking_account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require_relative 'account'

module Bank
class CheckingAccount < Account
def initialize (id, balance)
super(id, balance)
@checks = 0
end

def withdraw(withdraw_amount)

Choose a reason for hiding this comment

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

It might be cleaner to use super here to call Account#withdraw, and centralize your logic all in one place. In this case Account#withdraw would probably require more parameters, like a fee and a minimum balance.

fee = 1
if @balance < withdraw_amount
puts "You dont have enough funds!"
return @balance
end
@balance -= (withdraw_amount + fee)
end

def withdraw_using_check(amount)
raise ArgumentError.new("unvalid amount!") if amount < 0

if (@balance - amount) < -10
print "warning! Your balance would go under -$10"
return @balance
end
raise ArgumentError.new("No enough funds") if (@balance - amount) < -10

@checks += 1
fee = 2.0
return @balance -= (amount + fee) if @checks > 3
@balance -= amount
end

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

module Bank
class SavingsAccount < Account
def initialize(id, balance)
super(id, balance)
raise ArgumentError.new("balance must be >= 10") if balance < 10
end

def withdraw(withdraw_amount)
fee = 2
raise ArgumentError.new("Unvalid amount!") if withdraw_amount < 0
if (@balance - (withdraw_amount + fee)) < 10
print "warning! Your balance is less than 10 after fee applied"
return @balance
end

return @balance if (@balance -= (withdraw_amount + fee)) >= 10
end

def add_interest(rate)
raise ArgumentError.new("rate must be positive") if rate < 0

interest = @balance * rate
@balance += interest
end

end
end
57 changes: 33 additions & 24 deletions specs/account_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require 'minitest/reporters'
require 'minitest/skip_dsl'
require_relative '../lib/account'
require 'csv'
require 'date'

describe "Wave 1" do
describe "Account#initialize" do
Expand All @@ -18,10 +20,6 @@
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
Expand Down Expand Up @@ -61,13 +59,9 @@
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 Down Expand Up @@ -136,36 +130,51 @@
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
Bank::Account.all.must_be_instance_of Array
end

it "Returns the right numbers of accounts" do
num = 0
CSV.read("/Users/laurams/ada/homework/BankAccounts/support/accounts.csv").each do |line|
num +=1
end
Bank::Account.all.length.must_equal num
end

# TODO: Your test code here!
# Useful checks might include:
# - Account.all returns an array listo!!!
# - Everything in the array is an Account
# - The number of accounts is correct listo!!!!
# - 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

end

describe "Account.find" do
it "Returns an account that exists" do
# TODO: Your test code here!
#I am having trouble with this test sometimes.
#I think it's because the way I defined my @accounts_array.
#But the majority of times it passes. Wierd!
it "Returns an account that exits" do
Bank::Account.find(1212)
end

it "Can find the first account from the CSV" do
# TODO: Your test code here!
Bank::Account.all[0].id.must_equal 1212
end

Choose a reason for hiding this comment

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

Since this test is under describe "Account.find", it ought to be using the find method. How might you modify it to test what it says it tests?


it "Can find the last account from the CSV" do
# TODO: Your test code here!
Bank::Account.all[-1].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(0)
}.must_raise ArgumentError
end
end
end
99 changes: 72 additions & 27 deletions specs/checking_account_spec.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
require 'minitest/autorun'
require 'minitest/reporters'
require 'minitest/skip_dsl'
require_relative '../lib/checking_account'

# TODO: uncomment the next line once you start wave 3 and add lib/checking_account.rb
# require_relative '../lib/checking_account'

# Because a CheckingAccount is a kind
# of Account, and we've already tested a bunch of functionality
# on Account, we effectively get all that testing for free!
# Here we'll only test things that are different.

# TODO: change 'xdescribe' to 'describe' to run these tests
xdescribe "CheckingAccount" do
describe "CheckingAccount" do
describe "#initialize" do
# Check that a CheckingAccount is in fact a kind of account
it "Is a kind of Account" do
account = Bank::CheckingAccount.new(12345, 100.0)
account.must_be_kind_of Bank::Account
Expand All @@ -22,59 +13,113 @@

describe "#withdraw" do
it "Applies a $1 fee each time" do
# TODO: Your test code here!
start_balance = 100.0
withdrawal_amount = 25.0
fee = 1.0
account = Bank::CheckingAccount.new(1212, start_balance)

account.withdraw(withdrawal_amount)

expected_balance = start_balance - withdrawal_amount - fee
account.balance.must_equal expected_balance
end

it "Doesn't modify the balance if the fee would put it negative" do
# TODO: Your test code here!
start_balance = 100
withdraw_amount = 101
account = Bank::CheckingAccount.new(1212, start_balance)
x = account.withdraw(withdraw_amount)

x.must_equal start_balance
end
end

describe "#withdraw_using_check" do
it "Reduces the balance" do
# TODO: Your test code here!
start_balance = 876
amount = 76
account = Bank::CheckingAccount.new(17682, start_balance)
balance1 = start_balance - amount
account.withdraw_using_check(amount).must_be_same_as balance1
end

it "Returns the modified balance" do
# TODO: Your test code here!
start_balance = 100
amount = 70
account = Bank::CheckingAccount.new(17682, start_balance)
updated_balance = start_balance - amount

Choose a reason for hiding this comment

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

It looks like you removed a test here, possibly by accident?


updated_balance.must_equal account.withdraw_using_check(amount)
end

it "Allows the balance to go down to -$10" do
# TODO: Your test code here!
start_balance = 1000
withdrawal_amount = 1010
account = Bank::CheckingAccount.new(1879, start_balance)
account.withdraw_using_check(withdrawal_amount)
end

it "Outputs a warning if the account would go below -$10" do
# TODO: Your test code here!
end

it "Doesn't modify the balance if the account would go below -$10" do
# TODO: Your test code here!
start_balance = 1000
a = 2909
proc {
Bank::CheckingAccount.new(1879, start_balance).withdraw_using_check(a)
}.must_output (/.+/)
end

it "Requires a positive withdrawal amount" do
# TODO: Your test code here!
start_balance = 1000
a = -56
proc {
Bank::CheckingAccount.new(1879, start_balance).withdraw_using_check(a)
}.must_raise ArgumentError
end

it "Allows 3 free uses" do
# TODO: Your test code here!
balance = 100
amount = 10
account = Bank::CheckingAccount.new(17682, balance)
3.times {balance = balance - amount}

Choose a reason for hiding this comment

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

I like that you used times here to DRY up this code. Good work!

final_balance = 0
3.times {final_balance = account.withdraw_using_check(amount)}

final_balance.must_be_same_as balance
end

it "Applies a $2 fee after the third use" do
# TODO: Your test code here!
balance = 100
amount = 10
fee = 2
account = Bank::CheckingAccount.new(17682, balance)

4.times {balance = balance - amount}
balance -= fee
final_balance = nil
4.times {final_balance = account.withdraw_using_check(amount)}

final_balance.must_equal balance
end
end

describe "#reset_checks" do
it "Can be called without error" do
# TODO: Your test code here!
Bank::CheckingAccount.new(1819, 100).reset_checks
end

it "Makes the next three checks free if less than 3 checks had been used" do
# TODO: Your test code here!
account = Bank::CheckingAccount.new(8282, 100)
2.times {account.withdraw_using_check(10)}
account.reset_checks
3.times {account.withdraw_using_check(10)}
account.balance.must_equal 50
end

it "Makes the next three checks free if more than 3 checks had been used" do
# TODO: Your test code here!
account = Bank::CheckingAccount.new(8282, 100)
4.times {account.withdraw_using_check(10)}
account.reset_checks
3.times {account.withdraw_using_check(10)}
account.balance.must_equal 28
end
end
end
Loading