Skip to content

Commit

Permalink
Refactor implementation pieces in prep for #230.
Browse files Browse the repository at this point in the history
This splits each implementation piece into a separate object
so that it is easier to combine them.
  • Loading branch information
myronmarston committed Jun 18, 2013
1 parent 8d903ec commit 98bec84
Showing 1 changed file with 52 additions and 27 deletions.
79 changes: 52 additions & 27 deletions lib/rspec/mocks/message_expectation.rb
Expand Up @@ -25,7 +25,9 @@ def initialize(error_generator, expectation_ordering, expected_from, method_doub
@failed_fast = nil
@eval_context = nil
@implementation = implementation
@values_to_return = nil

@initial_implementation_logic = nil
@terminal_implementation_logic = nil
end

# @private
Expand Down Expand Up @@ -78,8 +80,7 @@ def and_return(*values, &implementation)
# TODO: deprecate `and_return { value }`
@implementation = implementation
else
@values_to_return = values
@implementation = build_implementation
self.terminal_implementation_logic = AndReturnImplementation.new(values)
end
end

Expand Down Expand Up @@ -154,7 +155,7 @@ def and_throw(*args)
def and_yield(*args, &block)
yield @eval_context = Object.new if block
@args_to_yield << args
@implementation = build_implementation
self.initial_implementation_logic = AndYieldImplementation.new(@args_to_yield, @eval_context, @error_generator)
self
end

Expand Down Expand Up @@ -418,7 +419,7 @@ def increase_actual_received_count!
@actual_received_count += 1
end

protected
private

def failed_fast?
@failed_fast
Expand All @@ -435,12 +436,20 @@ def set_expected_received_count(relativity, n)
end
end

private
def initial_implementation_logic=(logic)
@initial_implementation_logic = logic
update_implementation
end

def build_implementation
Implementation.new(
@values_to_return, @args_to_yield,
@eval_context, @error_generator
def terminal_implementation_logic=(logic)
@terminal_implementation_logic = logic
update_implementation
end

def update_implementation
@implementation = Implementation.new(
@initial_implementation_logic,
@terminal_implementation_logic
).method(:call)
end
end
Expand All @@ -462,29 +471,16 @@ def negative_expectation_for?(message)
end
end

# Represents a configured implementation. Takes into account
# `and_return` and `and_yield` instructions.
# Handles the implementation of an `and_yield` declaration.
# @private
class Implementation
def initialize(values_to_return, args_to_yield, eval_context, error_generator)
@values_to_return = values_to_return
class AndYieldImplementation
def initialize(args_to_yield, eval_context, error_generator)
@args_to_yield = args_to_yield
@eval_context = eval_context
@error_generator = error_generator
end

def call(*args_to_ignore, &block)
default_return_value = perform_yield(&block)
return default_return_value unless @values_to_return

if @values_to_return.size > 1
@values_to_return.shift
else
@values_to_return.first
end
end

def perform_yield(&block)
def call(*args_to_ignore, block)
return if @args_to_yield.empty? && @eval_context.nil?

@error_generator.raise_missing_block_error @args_to_yield unless block
Expand All @@ -498,5 +494,34 @@ def perform_yield(&block)
value
end
end

# Handles the implementation of an `and_return` implementation.
# @private
class AndReturnImplementation
def initialize(values_to_return)
@values_to_return = values_to_return
end

def call(*args_to_ignore, block)
if @values_to_return.size > 1
@values_to_return.shift
else
@values_to_return.first
end
end
end

# Represents a configured implementation. Takes into account
# any number of sub-implementations.
# @private
class Implementation
def initialize(*implementations)
@implementations = implementations.compact
end

def call(*args, &block)
@implementations.map { |i| i.call(*args, block) }.last
end
end
end
end

0 comments on commit 98bec84

Please sign in to comment.