Joe Joe - 3 months ago 7
Ruby Question

Change the value of a described_class.new argument

I have the following code:

require 'command'

describe Command do
subject(:command) { described_class.new(input, robotic_rover) }

let(:robotic_rover) do
double(:robotic_rover, position: '0 0 N',
move: '0 1 N',
right_turn: '0 0 E',
left_turn: '0 0 W')
end

describe 'advance command' do
let(:input) { 'M' }

describe 'initialization' do
it 'alters a rovers position' do
expect(command.position_change).to eq robotic_rover.move
end
end
end

describe 'right command' do
let(:input) { 'R' }

describe 'initialization' do
it 'alters a rovers direction' do
expect(command.position_change).to eq robotic_rover.right_turn
end
end
end

describe 'left command' do
let(:input) { 'L' }

describe 'initialization' do
it 'alters the rovers direction' do
expect(command.position_change).to eq robotic_rover.left_turn
end
end
end
end


Inside each of the initial describe blocks (advance command, right command and left command), I have attempted to define the value for the
input
argument passed into the
described_class.new(input, robotic_rover)
with a
let
.

What happens is that only the last test (left command), passes and the first two tests (advance command, and right command) fail with:

Failure/Error: expect(command.position_change).to eq robotic_rover.right_turn

expected: "0 0 E"
got: nil


If I remove the let from each of the first two tests, then they fail with:

Failure/Error: subject(:command) { described_class.new(input, robotic_rover) }

NameError:
undefined local variable or method `input' for #<RSpec::ExampleGroups::Command::AdvanceCommand::Initialization:0x007f90cc14f758>


can anyone help me with changing the value of that
initialize
argument for each of the describe blocks?

The Code

Intention with this code is to refactor it out of the multiple if's but for now, it's all I've got.

class Command
attr_reader :input, :robotic_rover

def initialize(input, robotic_rover)
@input = input
@robotic_rover = robotic_rover
end

def position_change
robotic_rover.move if input == 'M'
robotic_rover.right_turn if input == 'R'
robotic_rover.left_turn if input == 'L'
end
end

Answer

We are missing the return for each conditional in the #position_change method.

what is the point of return in Ruby?

class Command
  attr_reader :input, :robotic_rover

  def initialize(input, robotic_rover)
    @input         = input
    @robotic_rover = robotic_rover
  end

  def position_change
    return robotic_rover.move if input == 'M'
    return robotic_rover.right_turn if input == 'R'
    return robotic_rover.left_turn if input == 'L'
  end
end

describe Command do
  let(:instance) { described_class.new(input, robotic_rover) }

  let(:robotic_rover) do
    double(
      "RoboticRover",
      position: '0 0 N',
      move: '0 1 N',
      right_turn: '0 0 E',
      left_turn: '0 0 W'
    )
  end

  describe '#position_change' do
    subject(:position_change) { instance.position_change }

    context 'when advance command' do
      let(:input) { 'M' }

      it 'alters a rovers position' do
        expect(position_change).to eq robotic_rover.move
      end
    end

    context 'when right command' do
      let(:input) { 'R' }

      it 'alters a rovers direction' do
        expect(position_change).to eq robotic_rover.right_turn
      end
    end

    context 'when left command' do
      let(:input) { 'L' }

      it 'alters the rovers direction' do
        expect(position_change).to eq robotic_rover.left_turn
      end
    end
  end
end
Comments