Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# RSpec matcher to spec delegations.
# Forked from https://gist.github.com/txus/807456 with added bug fixes
#
# Usage:
#
# describe Post do
# it { should delegate(:name).to(:author).with_prefix } # post.author_name
# it { should delegate(:month).to(:created_at) }
# it { should delegate(:year).to(:created_at) }
# it { should delegate(:something).to(:'@instance_var') }
# end
RSpec::Matchers.define :delegate do |method|
match do |delegator|
@method = @prefix ? :"#{@to}_#{method}" : method
@delegator = delegator
if @to.to_s[0] == '@'
# Delegation to an instance variable
old_value = @delegator.instance_variable_get(@to)
begin
@delegator.instance_variable_set(@to, receiver_double(method))
@delegator.send(@method) == :called
ensure
@delegator.instance_variable_set(@to, old_value)
end
elsif @delegator.respond_to?(@to, true)
unless @delegator.method(@to).arity == 0
raise "#{@delegator}'s' #{@to} method does not have zero arity (it expects parameters)"
end
@delegator.stub(@to).and_return receiver_double(method)
@delegator.send(@method) == :called
else
raise "#{@delegator} does not respond to #{@to}"
end
end
description do
"delegate :#{@method} to its #{@to}#{@prefix ? ' with prefix' : ''}"
end
failure_message_for_should do |text|
"expected #{@delegator} to delegate :#{@method} to its #{@to}#{@prefix ? ' with prefix' : ''}"
end
failure_message_for_should_not do |text|
"expected #{@delegator} not to delegate :#{@method} to its #{@to}#{@prefix ? ' with prefix' : ''}"
end
chain(:to) { |receiver| @to = receiver }
chain(:with_prefix) { @prefix = true }
def receiver_double(method)
double('receiver').tap do |receiver|
receiver.stub(method).and_return :called
end
end
end
@seanselltl

This comment has been minimized.

Copy link

@seanselltl seanselltl commented Jul 9, 2013

I think that you should check if the method has an arity of -1 or 0 since either are valid.

@awinograd

This comment has been minimized.

Copy link

@awinograd awinograd commented Aug 5, 2013

Hi Simeon,

I've forked your gist at https://gist.github.com/awinograd/6158961.

It fixes the arity preoblem seanselltl metioned (which I also experienced) as well as adds support for a custom prefix for the delegation that can be added to the model's delegation.

delegate :name, to: :author, prefix: :any
it { should delegate(:name).to(:author).with_prefix(:any) } # post.any_name

@hrieke

This comment has been minimized.

Copy link

@hrieke hrieke commented May 20, 2020

Hello Simeon,
Do you have a license that you would like to release this code under?
I spoke with Alec Winograd about his fork, he's added an MIT License to his modifications.
Thank you, hope all is well.

@ssimeonov

This comment has been minimized.

Copy link
Owner Author

@ssimeonov ssimeonov commented May 20, 2020

I am happy to offer this code to the community under the MIT License.

@hrieke

This comment has been minimized.

Copy link

@hrieke hrieke commented May 21, 2020

Awesome and thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment