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
66 changes: 59 additions & 7 deletions lib/tree.rb
Original file line number Diff line number Diff line change
@@ -1,41 +1,93 @@
class NoApplesError < StandardError; end
class DeadTreeError < StandardError; end

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

def initialize
attr_reader :height, :age, :apples
Copy link
Member

Choose a reason for hiding this comment

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

nice! not everything needs to be settable.

attr_accessor :alive

def initialize(height: 0, age: 0, apples: [], alive: true, rand_seed: nil)
@height = height
@age = age
@apples = apples
@alive = alive
@prng = Random.new(rand_seed || Random.new_seed)
end

def age!
raise DeadTreeError, "This tree is dead" if self.dead?
@age += 1


# Simple check if a tree has become too old.
if @age >= 10 && age + @prng.rand(0..10) > 20
Copy link
Member

Choose a reason for hiding this comment

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

nice use of the getter here.

@alive = false
end

# What to do when a tree is alive and is aging
if @alive
inc_height!
add_apples
end
end

def inc_height!
@height += @prng.rand(1..3)
end

def add_apples
raise DeadTreeError, "This tree is dead" if self.dead?

count = @height * @prng.rand(1..3)
color = Apple.colors.sample
diameter = @prng.rand(4..8)

count.times { @apples.push(Apple.new(color, diameter)) }
end

def any_apples?
@apples.size > 0
end

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

def dead?
@alive == false
end
end


class Fruit
attr_reader :has_seeds

def initialize
has_seeds = true
@has_seeds = true
end
end

class Apple <
attr_reader #what should go here

class Apple < Fruit
attr_reader :color, :diameter

@@colors = ['red', 'yellow', 'green']
Copy link
Member

Choose a reason for hiding this comment

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

class variables arent recommended.

https://stackoverflow.com/questions/40819068/why-is-using-a-class-variable-in-ruby-considered-a-code-smell/40819118

instead you might use a constant or encapsulate them in a class method.

COLORS = %w(red yellow green).freeze
  def self.colors
    ['red', 'yellow', 'green']
  end

relatedly the cool thing about class << self is that you can use it to organize your private class methods in the same way you would handle instance methods.

class << self
  def foo
     bar
  end
  
  private

  def bar
    :baz
  end
end


class << self
def colors
@@colors
end
end

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


#THERES ONLY ONE THING YOU NEED TO EDIT BELOW THIS LINE
# avg_diameter (line 58) will raise an error.
# it should calculate the diameter of the apples in the basket
Expand All @@ -61,7 +113,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.to_f # It's up to you to calculate the average diameter for this harvest.

puts "Year #{tree.age} Report"
puts "Tree height: #{tree.height} feet"
Expand All @@ -76,4 +128,4 @@ def tree_data
end

# Uncomment this line to run the script, but BE SURE to comment it before you try to run your tests!
# tree_data
#tree_data
127 changes: 125 additions & 2 deletions spec/tree_spec.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,137 @@
require 'rspec'
require 'tree'

def kill_tree(tree)
# The 12 here is based off of the rand_seed the below
12.times { tree.age! }
Copy link
Member

Choose a reason for hiding this comment

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

this works but its preferred to either accomplish this with a helper method or let. https://relishapp.com/rspec/rspec-rails/v/3-7/docs/helper-specs/helper-spec

end

def new_test_tree
Copy link
Member

Choose a reason for hiding this comment

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

subject is a better option depending on what you're trying to convey.
you could also use let or let!` to accomplish this as well.

# Use a random seed here to make our tests predictable
tree = Tree.new(rand_seed: 100)
end

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

describe '#pick_an_apple!' do
it 'should raise when there are no apples' do
tree = new_test_tree
expect { tree.pick_an_apple! }.to raise_error(NoApplesError)
end

it 'shoud remove an apple' do
tree = new_test_tree
tree.age!
tree.pick_an_apple!
expect(tree.any_apples?).to eq false
end
end

describe '#any_apples?' do
it 'should return true when there are apples' do
tree = new_test_tree
Copy link
Member

Choose a reason for hiding this comment

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

the test tree can be setup as a variable placed in an outer context.

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

  describe "#kill" do
    context "when tree is alive" do
      it "kills tree"
         tree.kill
         expect(tree.dead?).to eq true
      end
    end
  end
end

tree.age!
expect(tree.any_apples?).to eq true
end

it 'should return false when there are not apples' do
tree = new_test_tree
expect(tree.any_apples?).to eq false
end
end

describe '#age!' do
it 'should increase the age of the tree' do
tree = new_test_tree
tree.age!
expect(tree.age).to eq 1
end

it 'should increase the height of the tree' do
tree = new_test_tree
tree.age!
expect(tree.height).to eq 1
end

it 'should raise when the tree is dead' do
tree = new_test_tree
kill_tree(tree)
expect { tree.age! }.to raise_error(DeadTreeError)
end

it 'should set alive to false when the tree is too old' do
tree = new_test_tree
kill_tree(tree)
expect(tree.age).to eq 12
expect(tree.dead?).to eq true
end

it 'should grow in height' do
tree = new_test_tree
previous_height = tree.height
tree.age!
expect(tree.height).to be > previous_height
end

it 'should grow more apples' do
tree = new_test_tree
previous_count = tree.apples.size
tree.age!
expect(tree.apples.size).to be > previous_count
end
end

describe '#dead?' do
it 'should return true when the tree is not alive' do
tree = new_test_tree
kill_tree(tree)
expect(tree.dead?).to eq true
end

it 'should return false when the tree is alive' do
tree = new_test_tree
expect(tree.dead?).to eq false
end
end

describe '#add_apples' do
it 'should raise when the tree is dead' do
tree = new_test_tree
kill_tree(tree)
expect { tree.add_apples }.to raise_error(DeadTreeError)
end

it 'should add apples ' do
tree = new_test_tree
expect(tree.any_apples?).to eq false
tree.age!
expect(tree.any_apples?).to eq true
end
end

describe '#inc_height!' do
it 'should increase the tree\'s height' do
tree = new_test_tree
tree.age!
expect(tree.height).to eq 1
end
end

end

describe 'Fruit' do
describe Fruit do
it 'should have seeds when created' do
f = Fruit.new
Copy link
Member

Choose a reason for hiding this comment

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

127..128 could also be written with subject or described_class

expect(f.has_seeds).to eq true
end
end

describe 'Apple' do
describe Apple do
it 'should have seeds when created' do
f = Apple.new('red', 1)
expect(f.has_seeds).to eq true
end
end