Skip to content

Commit be995c1

Browse files
committed
Feature: Handle symbol-to-proc wrappers (&:) that refer to a method created using delegation or method missing
These methods have an arity of -1
1 parent a4e3fcd commit be995c1

3 files changed

Lines changed: 51 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
### Next Release
22

3+
* [#406](https://github.com/ruby-grape/grape-entity/pull/406): Handle symbol-to-proc wrappers (`&:method_name`) where the method uses `delegate` or `method_missing`
4+
35
#### Features
46

57
* Your contribution here.

lib/grape_entity/entity.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,8 @@ def ensure_block_arity!(block)
548548
end
549549

550550
arity = object.method(origin_method_name).arity
551-
return if arity.zero?
551+
# functions defined using `delegate` or `method_missing` have an arity of -1
552+
return if arity <= 0
552553

553554
raise ArgumentError, <<~MSG
554555
Cannot use `&:#{origin_method_name}` because that method expects #{arity} argument#{'s' if arity != 1}.

spec/grape_entity/entity_spec.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ class BogusEntity < Grape::Entity
400400

401401
describe 'blocks' do
402402
class SomeObject
403+
class SomeObjectDelegate
404+
def method_using_delegation
405+
'delegated-result'
406+
end
407+
end
408+
409+
delegate :method_using_delegation, to: :delegate_object
410+
403411
def method_without_args
404412
'result'
405413
end
@@ -415,6 +423,23 @@ def method_with_multiple_args(_object, _options)
415423
def raises_argument_error
416424
raise ArgumentError, 'something different'
417425
end
426+
427+
def method_missing(method, ...)
428+
return 'missing-result' if method.to_sym == :method_using_missing
429+
430+
super
431+
end
432+
433+
def delegate_object
434+
@delegate_object ||= SomeObjectDelegate.new
435+
end
436+
437+
private
438+
439+
def respond_to_missing?(method, include_private = false)
440+
method.to_sym == :method_using_missing ||
441+
super
442+
end
418443
end
419444

420445
describe 'with block passed in' do
@@ -459,6 +484,28 @@ def raises_argument_error
459484
end
460485
end
461486

487+
context 'with block passed in via & that uses `missing_method`' do
488+
specify do
489+
subject.expose :using_missing, &:method_using_missing
490+
491+
object = SomeObject.new
492+
expect(object.method(:method_using_missing).arity).to eq(-1)
493+
value = subject.represent(object).value_for(:using_missing)
494+
expect(value).to eq('missing-result')
495+
end
496+
end
497+
498+
context 'with block passed in via & that uses `delegate`' do
499+
specify do
500+
subject.expose :using_delegation, &:method_using_delegation
501+
502+
object = SomeObject.new
503+
expect(object.method(:method_using_delegation).arity).to eq(-1)
504+
value = subject.represent(object).value_for(:using_delegation)
505+
expect(value).to eq('delegated-result')
506+
end
507+
end
508+
462509
context 'with block passed in via &' do
463510
specify do
464511
subject.expose :that_method_with_one_arg, &:method_with_one_arg

0 commit comments

Comments
 (0)