How to make this test pass, I'm a bit confused - ruby

this is my money class
class Money
def initialize
#amount = 0
end
def amount
#amount
end
def earn(this_many)
#amount += this_many
end
def spend(this_many)
#amount -= this_many
end
end
my failing test
def test_cant_spend_money_that_you_dont_have
money = Money.new
money.earn(75)
money.spend(75)
assert_equal "You can't spend what you don't have", money.spend(12)
assert_equal 0, money.amount
end
I'm not sure how to modify the amount method to make the test pass... any help will be appreciated.

You should raise errors when the account doesn't have enough money to spend.
class Money
class InsufficientFunds < StandardError; end
attr_accessor :amount
def initialize
self.amount = 0
end
def earn(this_many)
self.amount += this_many
end
def spend(this_many)
raise InsufficientFunds, "You can't spend what you don't have" if amount < this_many
self.amount -= this_many
end
end
And your test case should be
def test_cant_spend_money_that_you_dont_have
money = Money.new
money.earn(75)
money.spend(75)
assert_raise Money::InsufficientFunds, "You can't spend what you don't have" do
money.spend(12)
end
assert_equal 0, money.amount
end

I think you need to change
assert_equal "You can't spend what you don't have", money.spend(12)
to
money.spend(12)
assert money.amount > 0, "You can't spend what you don't have"

Related

Uninitialized constant Van (NameError)

I am trying to write some functionality which allows me to take a broken bike to a garage to have it fixed, whilst implementing this i have come across this issue. i understand that this usually is because it cannot find the file but have ran out of ideas on how to fix it. If you need any of the other code let me know but i thought this would be all the code needed.
dockingstation.rb:
require_relative 'Bike'
require_relative 'van'
require_relative 'garage'
class DockingStation
attr_reader :dock, :max_dock, :DEFAULT_CAPACITY
DEFAULT_CAPACITY = 20
def initialize(capacity = DEFAULT_CAPACITY)
#max_dock = capacity
#dock = []
end
def release_bike
if !empty?
#dock.each_with_index do |bike, index|
if bike.working?
#dock.delete_at(index)
return bike
else
raise "Bike is broken"
end
end
else
raise "No bikes to release"
end
end
def dock_bike(bike, working = true)
if !full?
#dock << bike
else
raise "Too many bikes"
end
end
def show_dock
#dock.each do |el|
return el
end
end
def van_takes_broken_bikes(van)
puts #dock
#dock.each_with_index do |bike, index|
if bike.working? == true
van.storage.append(bike)
else
van.storage.append(bike)
end
end
end
private def full?
#dock.length == #max_dock
end
private def empty?
#dock.length == 0
end
end
dock = DockingStation.new
bike = Bike.new
van = Van.new
bike.report_broken
dock.dock_bike(bike)
dock.van_takes_broken_bikes(van)
van.rb:
require_relative 'dockingstation'
require_relative 'garage'
class Van
attr_reader :storage
def initialize
#storage = []
end
def take_broken_bikes_to_garage(bikes)
end
end

How i can solve this issue ? undefined method for class

Have a problem, when run a code allways have error.
Expect: for the user add win or reduce his balance.
undefined method `balance=' for #<Dice:0x0000563d4d4dfd88 #name="foo", #balance=600, #bet=300>
Did you mean? balance
(repl):22:in `increase_decrease_cash'
(repl):62:in `<class:Game>'
(repl):29:in `<main>'
This error always comes out, retried everything I could guess, but nothing came of it and I don’t understand how it can be googled
class Dice
attr_accessor :name, :bet
attr_reader :balance
def initialize(name, balance, bet)
#name = name
#balance = balance
#bet = bet
end
def self.roll
#roll_dice = rand(1..2)
end
def self.check_bet
if #player.bet > #player.balance
puts "Enter number from 1 to #{#player.balance}"
end
end
def self.increase_decrease_cash
if #roll == #my_number
#player.balance += #player.bet
else
#player.balance -= #player.bet
end
end
end
class Game < Dice
#player = Dice.new("foo", 600, 0)
puts "Hello #{#player.name} your balance is: #{#player.balance}"
puts "Bones throwing count times"
a = 2 #gets.chomp.to_i
while a > 0 do
puts ""
puts "Enter your bet !!!"
# PLAYER BET
#player.bet = 300 #gets.chomp.to_i
check_bet
puts "Respected #{#player.name} your bet is: #{#player.bet}"
puts "Now select number 1-2"
# BONES ROLL
#my_number = roll # gets.chomp.to_i
puts "###################"
puts "Now we throw bones"
#roll = roll
puts "Nuber is #{roll}"
if #roll == #my_number
puts "Your win, you get #{#player.bet}"
else
puts "You lose #{#player.bet}"
end
p "$$$$"
p #player.balance
p "$$$$"
a -= 1
increase_decrease_cash
end
end
This error always comes out, retried everything I could guess, but nothing came of it and I don’t understand how it can be googled
attr_reader creates only the get method for balance. You need both get and set method for balance. Because you set balance in the initialize method. So, you should use attr_accessor instead of attr_reader.
attr_accessor :balance

Ruby: TDD Plus Coding

gem 'minitest', '~> 5.2'
# TDD
require 'minitest/autorun'
require 'minitest/pride'
require_relative 'kid'
class KidTest < Minitest::Test
def test_kid_has_not_eaten_sugar
kid = Kid.new
assert_equal 0, kid.grams_of_sugar_eaten
end
def test_kid_gets_5_grams_from_eating_candy
kid = Kid.new
kid.eat_candy
assert_equal 5, kid.grams_of_sugar_eaten
5.times { kid.eat_candy }
assert_equal 30, kid.grams_of_sugar_eaten
end
def test_kid_is_not_hyperactive
kid = Kid.new
refute kid.hyperactive?
end
def test_kid_is_hyperactive_after_60_grams_of_sugar
kid = Kid.new
11.times { kid.eat_candy }
refute kid.hyperactive?, "Not hyperactive yet..."
kid.eat_candy
assert kid.hyperactive?, "OK, now the kid is hyperactive."
end
end
# CODE
class Kid
attr_reader :grams_of_sugar_eaten
def initialize
#grams_of_sugar_eaten = 0
end
def eat_candy(grams = 5)
#grams_of_sugar_eaten += grams
end
def hyperactive?
false
end
end
Can anyone help direct me in the thinking that I should have as far as how to go about getting the 2nd test to pass and so on?
I'm not sure what to do make the test pass after the kid eats 5 grams of sugar and then after 5.times to have it pass after he eats 30 grams of sugar.
Appreciate any help
You've added eat_candy as an attr_reader, not a method. The initialize function here sets eat_candy to itself.
A possible fix:
class Kid
attr_reader :grams_of_sugar_eaten
def initialize
#grams_of_sugar_eaten = 0
end
def eat_candy(grams = 5)
#grams_of_sugar_eaten += grams
end
end

Cannot get a method instance to function; How to use an Each Do method in ruby?

I have an specific method that I would like to call so that I can see the balances for 'accounts'. The method is;
def report_balances(accounts)
accounts.each do |account|
puts account.balance
end
end
I am not sure but I have either built the above method incorrectly or I am calling it incorrectly or maybe I have placed the method correctly in my code.
class BankAccount
attr_reader :balance
def initialize(balance)
#balance = balance
end
def deposit(amount)
#balance += amount if amount >= 0
end
def withdraw(amount)
#balance -= amount if #balance >= amount
end
end
class SavingsAccount < BankAccount
attr_reader :number_of_withdrawals
APY = 0.0017
def initialize(balance)
super(balance) # calls the parent method
#number_of_withdrawals = 0 # then continues here
end
def end_of_month_closeout
if #balance > 0
interest_gained = (#balance * APY) / 12
#balance += interest_gained
end
#number_of_withdrawals = 0
end
def report_balances(accounts)
accounts.each do |account|
puts account.balance
end
end
end
I would like to see the balances of the objects:
my_account = SavingsAccount.new(100)
and
account = BankAccount.new(2500)
by calling
'report_balances(accounts)'
How would this be accomplished?
Think of my_account = SavingsAccount.new(100) as creating a new account, but what you're asking is I want to see all the balances of a list of accounts. Since each account has a balance, you can do:
[my_account, other_account].each do |account|
puts account.balance
end
I'd recommend moving your report_balances method to a class method or out of that class all together but that's a topic for a different discussion.

How do I use the inject method to calculate the balance instead of what I have now?

In the balance function, I am trying to calculate the balance using the inject method instead. Tried the documentation but couldn't get it..
I am new to Ruby and programming so any help would be appreciated..
class BankAccount
attr_reader :name
def initialize(name)
#name = name
#transactions = []
add_transaction("Beginning Balance", 0)
end
def credit(description, amount)
add_transaction(description, amount)
end
def debit(description, amount)
add_transaction(description, -amount)
end
def add_transaction(description, amount)
#transactions.push(description: description, amount: amount)
end
def balance
balance = 0.0
#transactions.each do |transaction|
balance += transaction[:amount]
end
return balance
end
def to_s
"Name: #{name}, Balance: #{sprintf("%0.2f", balance)}"
end
def print_register
puts "#{name}'s Bank Account"
puts "-" * 40
puts "Description".ljust(30) + "Amount".rjust(10)
#transactions.each do |transaction|
puts transaction[:description].ljust(30) + sprintf("%0.2f", transaction[:amount]).rjust(10)
end
puts "-" * 40
puts "Balance:".ljust(30) + sprintf("%0.2f", balance).rjust(10)
puts "-" * 40
end
end
Your example is great, as it's very easy to change the loop you have to an inject call:
def balance
#transactions.inject(0.0) { |balance, transaction| balance + transaction[:amount] }
end

Resources