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
33 changes: 29 additions & 4 deletions lib/tree.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,48 @@
class NoApplesError < StandardError; end

class Tree
attr_#fill_in :height, :age, :apples, :alive
attr_accessor :height, :age, :apples, :alive

def initialize
self.height ||= 0
self.age ||= 0
self.apples ||= []
self.alive = true
end

def age!
if self.age < 50
self.height += 1
end

if self.age == 99
self.alive = false
else
add_apples
end

self.age += 1
end

def add_apples
5.times do
diameter = Random.rand(2..4)
color = 'red'
apples[apples.length] = Apple.new(color, diameter)
end
end

def any_apples?
!apples.empty?
end

def pick_an_apple!
raise NoApplesError, "This tree has no apples" unless self.any_apples?
apples.shift
end

def dead?
!self.alive
Copy link
Member

Choose a reason for hiding this comment

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

You are consistently using the self.attribute for setting/changing values and just the bare attribute for reading values, except this one reader. Maybe change this one to !alive?

Copy link
Member

Choose a reason for hiding this comment

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

@mikegee what's your preference for defining attributes? ivars or using self as done here? And why? :D

Copy link
Member

Choose a reason for hiding this comment

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

I prefer defining the attribute methods and using them exclusively. Instance variables with typos raise no error, Ruby happily returns nil. Method calls with typos raise NoMethodError. I prefer feedback as early as possible.

Copy link
Member

Choose a reason for hiding this comment

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

On this particular line, I suggest removing the self. prefix but continuing to call the reader method.

end
end

Expand All @@ -29,10 +52,12 @@ def initialize
end
end

class Apple <
attr_reader #what should go here
class Apple < Fruit
attr_reader :color, :diameter

def initialize(color, diameter)
@color = color
@diameter = diameter
end
end

Expand Down Expand Up @@ -61,7 +86,7 @@ def tree_data
diameter_sum += apple.diameter
end

avg_diameter = # It's up to you to calculate the average diameter for this harvest.
avg_diameter = diameter_sum / basket.size

puts "Year #{tree.age} Report"
puts "Tree height: #{tree.height} feet"
Expand Down
128 changes: 126 additions & 2 deletions spec/tree_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,137 @@
require_relative '../lib/tree'

describe Tree do
let(:tree) { Tree.new }

it 'is a brand new tree' do
expect(tree.age).to eq 0
expect(tree.height).to eq 0
expect(tree.alive).to be_truthy
expect(tree.apples).to be_empty
end

it 'should be a Class' do
expect(described_class.is_a? Class).to eq true
end

describe '#age!' do
it 'increases the trees age' do
expect { tree.age! }.to change { tree.age }.by 1
end

context 'when the tree is young' do
before { tree.age = 5 }

it 'increases the trees height' do
expect { tree.age! }.to change { tree.height }.by 1
end

it 'adds apples to the tree' do
expect { tree.age! }.to change { tree.apples.count }.by 5
end
end

context 'when the tree is old' do
before { tree.age = 55 }

it 'does not increase the trees height' do
expect { tree.age! }.to_not change { tree.height }
end

it 'adds apples to the tree' do
expect { tree.age! }.to change { tree.apples.count }.by 5
end
end

context 'when the tree is about to die' do
before { tree.age = 99 }

it 'does not increase the trees height' do
expect { tree.age! }.to_not change { tree.height }
end

it 'does not add apples to the tree' do
expect { tree.age! }.to_not change { tree.apples.count }
end

it 'kills the tree' do
tree.age!
expect(tree.alive).to be_falsey
end
end
end

describe '#add_apples' do
it 'adds 5 apples to the tree' do
expect { tree.add_apples }.to change { tree.apples.count }.by 5
end
end

describe '#any_apples?' do
context 'when the tree doesnt have apples' do
before { tree.apples = [] }

it 'returns false' do
expect(tree.any_apples?).to be_falsey
end
end

context 'when the tree does have apples' do
before { tree.apples = [Apple.new('red', 2)]}

it 'returns true' do
expect(tree.any_apples?).to be_truthy
end
end
end

describe '#pick_an_apple!' do
before { tree.add_apples }

it 'returns an apple object' do
expect(tree.pick_an_apple!).to be_instance_of Apple
end

it 'removes the apple from the tree' do
expect { tree.pick_an_apple! }.to change { tree.apples.count } .by -1
end
end

describe '#dead?' do
context 'when the tree is alive' do
before { tree.alive = true }

it 'returns it is alive' do
expect(tree.dead?).to be_falsey
end
end

context 'when the tree is dead' do
before { tree.alive = false }

it 'returns it is dead' do
expect(tree.dead?).to be_truthy
end
end
end
end

describe 'Fruit' do
describe Fruit do
# I don't really use the fruit class at all
end

describe 'Apple' do
describe Apple do
let(:apple) { Apple.new('red', 2.5) }

it 'should be a Fruit' do
expect(apple).to be_a Fruit
end

it 'should have a color' do
expect(apple.color).to eq 'red'
end

it 'should have a diameter' do
expect(apple.diameter).to eq 2.5
end
end