Skip to content

Commit

Permalink
Fix regression in 2.14.
Browse files Browse the repository at this point in the history
`block.arity` on 1.8.7 can be a lie, apparently :(.
  • Loading branch information
myronmarston committed Jan 31, 2014
1 parent 952233e commit f99e995
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
7 changes: 7 additions & 0 deletions Changelog.md
@@ -1,6 +1,13 @@
### 2.14.5 Development
[full changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.4...v2.14.5)

Bug Fixes:

* Fix regression that caused block implementations to not receive all
args on 1.8.7 if the block also receives a block, due to Proc#arity
reporting `1` no matter how many args the block receives if it
receives a block, too. (Myron Marston)

### 2.14.4 / 2013-10-15
[full changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.3...v2.14.4)

Expand Down
25 changes: 21 additions & 4 deletions lib/rspec/mocks/message_expectation.rb
Expand Up @@ -520,10 +520,27 @@ def call(*args, &block)
end.last
end

def arg_slice_for(args, arity)
if arity >= 0
args.slice(0, arity)
else
if RUBY_VERSION.to_f > 1.8
def arg_slice_for(args, arity)
if arity >= 0
args.slice(0, arity)
else
args
end
end
else
# 1.8.7's `arity` lies somtimes:
# Given:
# def print_arity(&b) puts b.arity; end
#
# This prints 1:
# print_arity { |a, b, c, &bl| }
#
# But this prints 3:
# print_arity { |a, b, c| }
#
# Given that it lies, we can't trust it and we don't slice the args.
def arg_slice_for(args, arity)
args
end
end
Expand Down
11 changes: 11 additions & 0 deletions spec/rspec/mocks/block_return_value_spec.rb
@@ -1,6 +1,17 @@
require "spec_helper"

describe "a double declaration with a block handed to:" do
# The "receives a block" part is important: 1.8.7 has a bug that reports the
# wrong arity when a block receives a block.
it 'forwards all given args to the block, even when it receives a block', :unless => RUBY_VERSION.to_s == '1.8.6' do
obj = Object.new
yielded_args = []
eval("obj.stub(:foo) { |*args, &bl| yielded_args << args }")
obj.foo(1, 2, 3)

expect(yielded_args).to eq([[1, 2, 3]])
end

describe "should_receive" do
it "returns the value of executing the block" do
obj = Object.new
Expand Down

0 comments on commit f99e995

Please sign in to comment.