fix: Make CollectionDecorator respond_to? to ORM methods (#850)

## Testing
1. Create a decorator for the model and its association
```ruby
class OrderHistoryDecorator < Draper::Decorator
  delegate_all
end

class OrderDecorator < Draper::Decorator
  delegate_all

  decorates_association :order_histories, with: OrderHistoryDecorator
end
```

2. Call `respond_to?` with some ORM method allowed by the strategy
```ruby
[1] pry(main)> order.order_histories.decorate.respond_to?(:includes)
=> true
```

## References
* method_missing [usage](https://thoughtbot.com/blog/always-define-respond-to-missing-when-overriding)
This commit is contained in:
Bruno Castro 2019-03-16 16:15:16 -03:00 committed by Cliff Braton
parent 395b647fc2
commit 5e4f529bb8
2 changed files with 31 additions and 3 deletions

View File

@ -9,6 +9,10 @@ module Draper
object.send(method, *args, &block).decorate
end
def respond_to_missing?(method, include_private = false)
strategy.allowed?(method) || super
end
private
# Configures the strategy used to proxy the query methods, which defaults to `:active_record`.

View File

@ -5,12 +5,13 @@ Post = Struct.new(:id) { }
module Draper
describe QueryMethods do
let(:fake_strategy) { instance_double(QueryMethods::LoadStrategy::ActiveRecord) }
before { allow(QueryMethods::LoadStrategy).to receive(:new).and_return(fake_strategy) }
describe '#method_missing' do
let(:collection) { [ Post.new, Post.new ] }
let(:collection_decorator) { PostDecorator.decorate_collection(collection) }
let(:fake_strategy) { instance_double(QueryMethods::LoadStrategy::ActiveRecord) }
before { allow(QueryMethods::LoadStrategy).to receive(:new).and_return(fake_strategy) }
context 'when strategy allows collection to call the method' do
let(:results) { spy(:results) }
@ -35,5 +36,28 @@ module Draper
end
end
end
describe "#respond_to?" do
let(:collection) { [ Post.new, Post.new ] }
let(:collection_decorator) { PostDecorator.decorate_collection(collection) }
subject { collection_decorator.respond_to?(:some_query_method) }
context 'when strategy allows collection to call the method' do
before do
allow(fake_strategy).to receive(:allowed?).with(:some_query_method).and_return(true)
end
it { is_expected.to eq(true) }
end
context 'when strategy does not allow collection to call the method' do
before do
allow(fake_strategy).to receive(:allowed?).with(:some_query_method).and_return(false)
end
it { is_expected.to eq(false) }
end
end
end
end