Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #406 from haines/collection_decorator

Unfreeze collection decorator
  • Loading branch information...
commit c6d60e6577ed396385f3f1151c3f188fe47e9a57 2 parents e4fa239 + 68151a8
@steveklabnik steveklabnik authored
View
15 lib/draper/collection_decorator.rb
@@ -3,20 +3,17 @@ class CollectionDecorator
include Enumerable
include ViewHelpers
- attr_reader :source
- alias_method :to_source, :source
-
attr_accessor :context
array_methods = Array.instance_methods - Object.instance_methods
- delegate :as_json, *array_methods, to: :decorated_collection
+ delegate :==, :as_json, *array_methods, to: :decorated_collection
# @param source collection to decorate
# @option options [Class] :with the class used to decorate items
# @option options [Hash] :context context available to each item's decorator
def initialize(source, options = {})
options.assert_valid_keys(:with, :context)
- @source = source.to_a.dup.freeze
+ @source = source
@decorator_class = options[:with]
@context = options.fetch(:context, {})
end
@@ -26,7 +23,7 @@ class << self
end
def decorated_collection
- @decorated_collection ||= source.map{|item| decorate_item(item)}.freeze
+ @decorated_collection ||= source.map{|item| decorate_item(item)}
end
def find(*args, &block)
@@ -37,10 +34,6 @@ def find(*args, &block)
end
end
- def ==(other)
- source == (other.respond_to?(:source) ? other.source : other)
- end
-
def to_s
klass = begin
decorator_class
@@ -62,6 +55,8 @@ def decorator_class
protected
+ attr_reader :source
+
def decorate_item(item)
item_decorator.call(item, context: context)
end
View
35 spec/draper/collection_decorator_spec.rb
@@ -16,27 +16,6 @@
subject.map{|item| item.source}.should == source
end
- describe "#source" do
- it "duplicates the source collection" do
- subject.source.should == source
- subject.source.should_not be source
- end
-
- it "is frozen" do
- subject.source.should be_frozen
- end
-
- it "is aliased to #to_source" do
- subject.to_source.should == source
- end
- end
-
- describe "#decorated_collection" do
- it "is frozen" do
- subject.decorated_collection.should be_frozen
- end
- end
-
context "with context" do
subject { Draper::CollectionDecorator.new(source, with: ProductDecorator, context: {some: 'context'}) }
@@ -151,7 +130,6 @@
describe "#find" do
context "with a block" do
it "decorates Enumerable#find" do
- subject.stub decorated_collection: []
subject.decorated_collection.should_receive(:find)
subject.find {|p| p.title == "title" }
end
@@ -208,13 +186,12 @@
describe "#to_ary" do
# required for `render @collection` in Rails
it "delegates to the decorated collection" do
- subject.stub decorated_collection: double(to_ary: :an_array)
+ subject.decorated_collection.stub to_ary: :an_array
subject.to_ary.should == :an_array
end
end
it "delegates array methods to the decorated collection" do
- subject.stub decorated_collection: []
subject.decorated_collection.should_receive(:[]).with(42).and_return(:the_answer)
subject[42].should == :the_answer
end
@@ -251,6 +228,16 @@
a.should_not == b
end
end
+
+ context "when the decorated collection has been modified" do
+ it "is no longer equal to the source" do
+ a = Draper::CollectionDecorator.new(source, with: ProductDecorator)
+ b = source.dup
+
+ a << Product.new.decorate
+ a.should_not == b
+ end
+ end
end
describe "#to_s" do
View
2  spec/draper/decoratable_spec.rb
@@ -150,7 +150,7 @@
decorator.should be_a Draper::CollectionDecorator
decorator.decorator_class.should be WidgetDecorator
- decorator.source.should == Product.scoped
+ decorator.should == Product.scoped
end
it "accepts context" do
View
4 spec/draper/decorated_association_spec.rb
@@ -86,9 +86,9 @@
let(:options) { {scope: :foo} }
it "applies the scope before decoration" do
- scoped = [:scoped]
+ scoped = [Product.new]
associated.should_receive(:foo).and_return(scoped)
- decorated_association.call.source.should == scoped
+ decorated_association.call.should == scoped
end
end
end
View
2  spec/draper/decorator_spec.rb
@@ -94,7 +94,7 @@
it "returns a collection decorator" do
subject.should be_a Draper::CollectionDecorator
- subject.source.should == source
+ subject.should == source
end
it "uses itself as the item decorator by default" do
View
2  spec/draper/finders_spec.rb
@@ -73,7 +73,7 @@
Product.stub(:find_all_by_name).and_return(found)
decorator = ProductDecorator.find_all_by_name("apples")
decorator.should be_a Draper::CollectionDecorator
- decorator.source.should == found
+ decorator.should == found
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.