diff --git a/lib/dynamoid/associations/single_association.rb b/lib/dynamoid/associations/single_association.rb index 7d862595..80a5a579 100644 --- a/lib/dynamoid/associations/single_association.rb +++ b/lib/dynamoid/associations/single_association.rb @@ -64,18 +64,37 @@ def ==(other) target == other end - # Delegate methods we don't find directly to the target. - # - # @private - # @since 0.2.0 - def method_missing(method, *args) - if target.respond_to?(method) - target.send(method, *args) - else - super + if ::RUBY_VERSION < '2.7' + # Delegate methods we don't find directly to the target. + # + # @private + # @since 0.2.0 + def method_missing(method, *args, &block) + if target.respond_to?(method) + target.send(method, *args, &block) + else + super + end + end + else + # Delegate methods we don't find directly to the target. + # + # @private + # @since 0.2.0 + def method_missing(method, *args, **kwargs, &block) + if target.respond_to?(method) + target.send(method, *args, **kwargs, &block) + else + super + end end end + # @private + def respond_to_missing?(method_name, include_private = false) + target.respond_to?(method_name, include_private) || super + end + # @private def nil? target.nil? diff --git a/spec/app/models/magazine.rb b/spec/app/models/magazine.rb index ea2e24b5..bc534999 100644 --- a/spec/app/models/magazine.rb +++ b/spec/app/models/magazine.rb @@ -12,4 +12,10 @@ class Magazine has_one :sponsor belongs_to :owner, class_name: 'User', inverse_of: :books + + def publish(advertisements:, free_issue: false) + result = advertisements * (free_issue ? 2 : 1) + result = yield(result) if block_given? + result + end end diff --git a/spec/dynamoid/associations/belongs_to_spec.rb b/spec/dynamoid/associations/belongs_to_spec.rb index 35454725..cc723de2 100644 --- a/spec/dynamoid/associations/belongs_to_spec.rb +++ b/spec/dynamoid/associations/belongs_to_spec.rb @@ -30,11 +30,23 @@ expect(user.books).to include magazine end - it 'behaves like the object it is trying to be' do - expect(magazine.subscriptions).to include subscription - subscription.magazine.update_attribute(:size, 101) + context 'proxied behavior' do + let(:proxy) do + expect(magazine.subscriptions).to include(subscription) + subscription.magazine + end + + it 'forwards dynamoid methods' do + proxy.update_attribute(:size, 101) - expect(Magazine.first.size).to eq 101 + expect(Magazine.first.size).to eq 101 + end + + it 'forwards business-logic methods' do + expect(proxy.respond_to?(:publish)).to eq true + expect(proxy.publish(advertisements: 10)).to eq 10 + expect(proxy.publish(advertisements: 10, free_issue: true) { |c| c *= 42 }).to eq 840 + end end end