Skip to content

Commit

Permalink
Add with_prefix to delegate_method
Browse files Browse the repository at this point in the history
Secondary author: Elliot Winkler <elliot.winkler@gmail.com>
  • Loading branch information
Aditya Kapoor authored and mcmire committed Dec 16, 2014
1 parent f82d4ee commit 18201d4
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 2 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
* Change `set_session` so that its #to qualifier supports regexps, similar to
`set_flash`.

* Add `with_prefix` qualifier to `delegate_method` to correspond to the `prefix`
option for Rails's `delegate` macro. [#622]

### Improvements

* Tweak `allow_value` failure message so that it reads a bit nicer when listing
Expand All @@ -79,6 +82,7 @@
[#598]: https://github.com/thoughtbot/shoulda-matchers/pull/598
[#602]: https://github.com/thoughtbot/shoulda-matchers/pull/602
[#543]: https://github.com/thoughtbot/shoulda-matchers/pull/543
[#622]: https://github.com/thoughtbot/shoulda-matchers/pull/622

# 2.7.0

Expand Down
58 changes: 56 additions & 2 deletions lib/shoulda/matchers/independent/delegate_method_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,24 @@ module Independent
# should delegate_method(:deliver).to(:post_office)
# end
#
# You can also use `delegate_method` with Rails's `delegate` macro:
#
# class Courier
# attr_reader :post_office
# delegate :deliver, to: :post_office
#
# def initialize
# @post_office = PostOffice.new
# end
# end
#
# describe Courier do
# it { should delegate_method(:deliver).to(:post_office) }
# end
#
# To employ some terminology, we would say that Courier's #deliver method
# is the delegating method, PostOffice is the delegate object, and
# PostOffice#deliver is the delegate method.
# is the *delegating method*, PostOffice is the *delegate object*, and
# PostOffice#deliver is the *delegate method*.
#
# #### Qualifiers
#
Expand Down Expand Up @@ -67,6 +82,31 @@ module Independent
# should delegate_method(:deliver).to(:post_office).as(:ship)
# end
#
# ##### with_prefix
#
# Use `with_prefix` when using Rails's `delegate` helper along with the
# `:prefix` option.
#
# class Page < ActiveRecord::Base
# belongs_to :site
# delegate :name, to: :site, prefix: true
# delegate :title, to: :site, prefix: :root
# end
#
# # RSpec
# describe Page do
# it { should delegate_method(:name).to(:site).with_prefix }
# it { should delegate_method(:name).to(:site).with_prefix(true) }
# it { should delegate_method(:title).to(:site).with_prefix(:root) }
# end
#
# # Test::Unit
# class PageTest < Test::Unit::TestCase
# should delegate_method(:name).to(:site).with_prefix
# should delegate_method(:name).to(:site).with_prefix(true)
# should delegate_method(:title).to(:site).with_prefix(:root)
# end
#
# ##### with_arguments
#
# Use `with_arguments` to assert that the delegate method is called with
Expand Down Expand Up @@ -170,6 +210,20 @@ def with_arguments(*arguments)
self
end

def with_prefix(prefix = nil)
@delegating_method =
:"#{build_delegating_method_prefix(prefix)}_#{delegate_method}"
delegate_method
self
end

def build_delegating_method_prefix(prefix)
case prefix
when true, nil then delegate_object_reader_method
else prefix
end
end

def failure_message
"Expected #{class_under_test} to #{description}\n" +
"Method calls sent to " +
Expand Down
218 changes: 218 additions & 0 deletions spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,76 @@
expect(matcher.description).to eq message
end
end

context 'qualified with #with_prefix' do
context 'without arguments' do
before do
define_model('Country') do
def hello; 'hello' end
end
end

context "when the subject's delegating method also has a prefix" do
it 'produces the correct description' do
define_class('Person') do
delegate :hello, to: :country, prefix: true

def country
Country.new
end
end

matcher = delegate_method(:hello).to(:country).with_prefix
expect(matcher.description).
to eq('delegate #country_hello to #country object as #hello')
end
end
end

context 'as true' do
before do
define_model('Country') do
def hello; 'hello' end
end
end

context "when the subject's delegating method also has a prefix" do
it 'produces the correct description' do
define_class('Person') do
delegate :hello, to: :country, prefix: true

def country
Country.new
end
end

matcher = delegate_method(:hello).to(:country).with_prefix(true)
expect(matcher.description).
to eq('delegate #country_hello to #country object as #hello')
end
end
end

context 'as a symbol/string' do
it 'should delegate as (prefix_supplied)_(method_on_target)' do
define_model('Country') do
def hello; 'hello' end
end

define_class('Person') do
delegate :hello, to: :country, prefix: 'county'

def country
Country.new
end
end

matcher = delegate_method(:hello).to(:country).with_prefix('county')
expect(matcher.description).
to eq('delegate #county_hello to #country object as #hello')
end
end
end
end

context 'when the subject is a class' do
Expand Down Expand Up @@ -296,4 +366,152 @@ def mailman
end
end
end

context 'qualified with #with_prefix' do
context 'without arguments' do
before do
define_model('Country') do
def hello; 'hello' end
end
end

context "when the subject's delegating method also has a prefix" do
it 'accepts' do
define_class('Person') do
delegate :hello, to: :country, prefix: true

def country
Country.new
end
end

person = Person.new
expect(person).to delegate_method(:hello). to(:country).with_prefix
end
end

context "when the subject's delegating method does not have a prefix" do
it 'rejects with the correct failure message' do
define_class('Person') do
delegate :hello, to: :country

def country
Country.new
end
end

message = [
'Expected Person to delegate #country_hello to #country object as #hello',
'Method calls sent to Person#country: (none)'
].join("\n")

person = Person.new

expect {
expect(person).to delegate_method(:hello). to(:country).with_prefix
}.to fail_with_message(message)
end
end
end

context 'as true' do
before do
define_model('Country') do
def hello; 'hello' end
end
end

context "when the subject's delegating method also has a prefix" do
it 'accepts' do
define_class('Person') do
delegate :hello, to: :country, prefix: true

def country
Country.new
end
end

person = Person.new
expect(person).
to delegate_method(:hello).
to(:country).with_prefix(true)
end
end

context "when the subject's delegating method does not have a prefix" do
it 'rejects with the correct failure message' do
define_class('Person') do
delegate :hello, to: :country

def country
Country.new
end
end

message = [
'Expected Person to delegate #country_hello to #country object as #hello',
'Method calls sent to Person#country: (none)'
].join("\n")

person = Person.new

expect {
expect(person).
to delegate_method(:hello).
to(:country).with_prefix(true)
}.to fail_with_message(message)
end
end
end

context 'as a symbol/string' do
before do
define_model('Country') do
def hello; 'hello' end
end
end

context "when the subject's delegating method has the same prefix" do
it 'accepts' do
define_class('Person') do
delegate :hello, to: :country, prefix: 'county'

def country
Country.new
end
end

person = Person.new
expect(person).
to delegate_method(:hello).
to(:country).with_prefix('county')
end
end

context "when the subject's delegating method has a different prefix" do
it 'rejects with the correct failure message' do
define_class('Person') do
delegate :hello, to: :country, prefix: 'something_else'

def country
Country.new
end
end

message = [
'Expected Person to delegate #county_hello to #country object as #hello',
'Method calls sent to Person#country: (none)'
].join("\n")

person = Person.new

expect {
expect(person).
to delegate_method(:hello).
to(:country).with_prefix('county')
}.to fail_with_message(message)
end
end
end
end
end

0 comments on commit 18201d4

Please sign in to comment.