ogirginc ogirginc - 5 days ago 4
Ruby Question

Boolean argument error in Ruby

I am working on POODR's chapter 8, Combining Objects with Composition. However, I can't seem to make the example work:

class Bicycle
attr_reader :size, :parts

def initialize(args = {})
@size = args[:size]
@parts = args[:parts]
end

def spares
parts.spares
end
end





require 'forwardable'
class Parts
extend Forwardable
def_delegators :@parts, :size, :each
include Enumerable

def initialize(parts)
@parts = parts
end

def spares
select { |part| part.needs_spare }
end
end





require 'ostruct'
module PartsFactory
def self.build(config, parts_class = Parts)
parts_class.new(
config.collect do |part_config|
create_part(part_config)
end
)
end

def self.create_part(part_config)
OpenStruct.new(
name: part_config[0],
description: part_config[1],
needs_spare: part_config.fetch(2, true)
)
end
end





When I use
road_config
:

road_config =
[['chain', '10-speed'],
['tire_size', '23'],
['tape_color', 'red']]

road_bike =
Bicycle.new(
size: 'L',
parts: PartsFactory.build(road_config)
)

p road_bike.spares.size


road_bike.spares.size
returns 3. Which is what I expected. However, when I use
mountain_config
:

mountain_config =
[['chain', '10-speed'],
['tire_size', '2.1'],
['front_shock', 'Manitou', false],
['rear_shock', 'Fox']]

mountain_bike =
Bicycle.new(
size: 'L',
parts: PartsFactory.build(mountain_config)
)

p mountain_bike.spares.size


I was expecting to see 4, not 3. If I delete
false
from
front_shock
to let it to the default value (
true
),
mountain_bike.spares.size
returns 4.

Why
false
makes
mountain_bike.spares.size
return 3? What am I missing?

Answer

Because it doesn't need a spare - in your parts class, you are selecting the parts that need a spare:

def spares
  select { |part| part.needs_spare }
end

That code will return the parts that need spares (i.e. needs_spare is true). The false in the config for front_shock sets this to false. Try setting other parts' needs_spare value to false to see what I mean.