Skip to content

Instantly share code, notes, and snippets.

@txus
Created February 2, 2011 09:19
Show Gist options
  • Save txus/807456 to your computer and use it in GitHub Desktop.
Save txus/807456 to your computer and use it in GitHub Desktop.
RSpec matcher for delegations
# RSpec matcher to spec delegations.
#
# 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) }
# end
RSpec::Matchers.define :delegate do |method|
match do |delegator|
@method = @prefix ? :"#{@to}_#{method}" : method
@delegator = delegator
begin
@delegator.send(@to)
rescue NoMethodError
raise "#{@delegator} does not respond to #{@to}!"
end
@delegator.stub(@to).and_return double('receiver')
@delegator.send(@to).stub(method).and_return :called
@delegator.send(@method) == :called
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 }
end
@fbjork
Copy link

fbjork commented Feb 3, 2011

Been looking for something like this, awesome work!

However, I get this error when I try to run this matcher:
it { should delegate(:name).to(:profile)}
error:
id is required for non-singleton resources

any idea what's going?

@txus
Copy link
Author

txus commented Feb 5, 2011

I'm afraid it has nothing to do with the delegator... Could you provide a full backtrace and maybe also the code for your model?

@jsnrth
Copy link

jsnrth commented Jun 10, 2011

Exactly what I needed – thanks! -j

@isaacbowen
Copy link

Thanks!

@pcreux
Copy link

pcreux commented Dec 1, 2011

Cool thanks!

@tshchik
Copy link

tshchik commented Mar 18, 2012

Thanks!

@cveneziani
Copy link

Awesome! Very useful.

@dankozlowski
Copy link

You should try to get this into Shoulda!

@ssimeonov
Copy link

This is cool but there are three small problems with this implementation:

  1. It does not work in the case of delegating to instance variables, e.g., delegate :foo, to: :'@my_var'
  2. Validating that the delegation target exists by using @delegator.send(@to) is an unexpected behavior from the standpoint of the user of the matcher. If there are any side effects from that call, the test outcome could be affected.
  3. The rescue block won't catch arity-related errors.

All three issues are fixed in my fork: https://gist.github.com/ssimeonov/5942729

@bparanj
Copy link

bparanj commented Nov 3, 2015

This fails if the method is a setter with error:

 Failure/Error: it{ should delegate(:name=).to(:sku_description)}

@bparanj
Copy link

bparanj commented Nov 3, 2015

My fork has updated this gist to RSpec 3.3 version: https://gist.github.com/bparanj/4579700adca0b64e7ca0

@nelantone
Copy link

Hahah! @txus ! Te veo hasta en la sopa :).

@hrieke
Copy link

hrieke commented May 20, 2020

Hello,

Do you have a license that you would like to release this code under?
I spoke with Alec Winograd about his fork-of-Simeon's-fork (yep, 2 down), he's added an MIT License to his modifications.
I have also asked Simeon if he'd like to add a license to his modification, but it would be absolutely wonderful if you could assign a license to your code. [Edit] Simeon Simeonov has replied, and selected the MIT License for his modifications as well. [/Edit]

Thank you, hope all is well.

@julienbourdeau
Copy link

I'm using this for now but thanks for the original work 👏 ❤️

➡️ https://gist.github.com/purp/fe5f79e878b609560724d6b03242a5df

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