Skip to content

Commit cc14f92

Browse files
committed
Fix single-argument lambda regression in exec_with_object
PR #389 changed arity detection to use block.arity.zero? which broke single-argument lambdas in expose blocks and if: conditions, causing ArgumentError (given 2, expected 1). Restore parameter count check for regular blocks while keeping symbol-to-proc detection intact. Fixes #398
1 parent bb355c8 commit cc14f92

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

lib/grape_entity/entity.rb

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -525,13 +525,10 @@ def serializable_hash(runtime_options = {})
525525
end
526526

527527
def exec_with_object(options, &block)
528-
arity = if symbol_to_proc_wrapper?(block)
529-
ensure_block_arity!(block)
530-
else
531-
block.arity
532-
end
533-
534-
if arity.zero?
528+
if symbol_to_proc_wrapper?(block)
529+
ensure_block_arity!(block)
530+
instance_exec(object, &block)
531+
elsif block.parameters.one?
535532
instance_exec(object, &block)
536533
else
537534
instance_exec(object, options, &block)

spec/grape_entity/entity_spec.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,30 @@ def raises_argument_error
476476
end.to raise_error ArgumentError, match(/method is not defined in the object/)
477477
end
478478
end
479+
480+
context 'with single-argument lambda' do
481+
it 'passes only the object without raising ArgumentError' do
482+
subject.expose :that_method_without_args do |object|
483+
object.method_without_args
484+
end
485+
486+
object = SomeObject.new
487+
value = subject.represent(object).value_for(:that_method_without_args)
488+
expect(value).to eq('result')
489+
end
490+
end
491+
492+
context 'with two-argument lambda' do
493+
it 'passes the object and options without raising ArgumentError' do
494+
subject.expose :that_method_without_args do |object, _options|
495+
object.method_without_args
496+
end
497+
498+
object = SomeObject.new
499+
value = subject.represent(object).value_for(:that_method_without_args)
500+
expect(value).to eq('result')
501+
end
502+
end
479503
end
480504

481505
context 'with no parameters passed to the block' do
@@ -521,6 +545,32 @@ def raises_argument_error
521545
expect(subject.represent({}).value_for(:awesome)).to eq(condition_met: 'value')
522546
end
523547

548+
it 'works with single-argument if condition lambdas' do
549+
subject.expose :awesome do
550+
subject.expose(:condition_met, if: ->(_) { true }) { |_| 'value' }
551+
subject.expose(:condition_not_met, if: ->(_) { false }) { |_| 'value' }
552+
end
553+
554+
expect(subject.represent({}).value_for(:awesome)).to eq(condition_met: 'value')
555+
end
556+
557+
it 'works with two-argument if condition lambdas' do
558+
subject.expose :awesome do
559+
subject.expose(:condition_met, if: ->(_, _) { true }) { |_| 'value' }
560+
subject.expose(:condition_not_met, if: ->(_, _) { false }) { |_| 'value' }
561+
end
562+
563+
expect(subject.represent({}).value_for(:awesome)).to eq(condition_met: 'value')
564+
end
565+
566+
it 'works with single-argument block exposures' do
567+
subject.expose :awesome do
568+
subject.expose(:nested) { |obj| obj.class.name }
569+
end
570+
571+
expect(subject.represent({}).value_for(:awesome)).to eq(nested: 'Hash')
572+
end
573+
524574
it 'does not represent attributes, declared inside nested exposure, outside of it' do
525575
subject.expose :awesome do
526576
subject.expose(:nested) { |_| 'value' }

0 commit comments

Comments
 (0)