From f4b21284f4ebb5e71b40b12a0f4bcda6d436088c Mon Sep 17 00:00:00 2001 From: Jeff Casimir Date: Fri, 10 Apr 2015 15:05:22 -0600 Subject: [PATCH] Blow up Decoratable --- lib/draper.rb | 1 - lib/draper/decoratable.rb | 96 ----------- spec/draper/decoratable/equality_spec.rb | 10 -- spec/draper/decoratable_spec.rb | 202 ----------------------- spec/spec_helper.rb | 2 +- 5 files changed, 1 insertion(+), 310 deletions(-) delete mode 100644 lib/draper/decoratable.rb delete mode 100644 spec/draper/decoratable/equality_spec.rb delete mode 100644 spec/draper/decoratable_spec.rb diff --git a/lib/draper.rb b/lib/draper.rb index 351a81c..ac5fadb 100644 --- a/lib/draper.rb +++ b/lib/draper.rb @@ -16,7 +16,6 @@ require 'draper/finders' require 'draper/decorator' require 'draper/helper_proxy' require 'draper/lazy_helpers' -require 'draper/decoratable' require 'draper/factory' require 'draper/decorated_association' require 'draper/helper_support' diff --git a/lib/draper/decoratable.rb b/lib/draper/decoratable.rb deleted file mode 100644 index 3771e57..0000000 --- a/lib/draper/decoratable.rb +++ /dev/null @@ -1,96 +0,0 @@ -require 'draper/decoratable/equality' - -module Draper - # Provides shortcuts to decorate objects directly, so you can do - # `@product.decorate` instead of `ProductDecorator.new(@product)`. - # - # This module is included by default into `ActiveRecord::Base` and - # `Mongoid::Document`, but you're using another ORM, or want to decorate - # plain old Ruby objects, you can include it manually. - module Decoratable - extend ActiveSupport::Concern - include Draper::Decoratable::Equality - - # Decorates the object using the inferred {#decorator_class}. - # @param [Hash] options - # see {Decorator#initialize} - def decorate(options = {}) - decorator_class.decorate(self, options) - end - - # (see ClassMethods#decorator_class) - def decorator_class - self.class.decorator_class - end - - def decorator_class? - self.class.decorator_class? - end - - # The list of decorators that have been applied to the object. - # - # @return [Array] `[]` - def applied_decorators - [] - end - - # (see Decorator#decorated_with?) - # @return [false] - def decorated_with?(decorator_class) - false - end - - # Checks if this object is decorated. - # - # @return [false] - def decorated? - false - end - - module ClassMethods - - # Decorates a collection of objects. Used at the end of a scope chain. - # - # @example - # Product.popular.decorate - # @param [Hash] options - # see {Decorator.decorate_collection}. - def decorate(options = {}) - collection = Rails::VERSION::MAJOR >= 4 ? all : scoped - decorator_class.decorate_collection(collection, options.reverse_merge(with: nil)) - end - - def decorator_class? - decorator_class - rescue Draper::UninferrableDecoratorError - false - end - - # Infers the decorator class to be used by {Decoratable#decorate} (e.g. - # `Product` maps to `ProductDecorator`). - # - # @return [Class] the inferred decorator class. - def decorator_class - prefix = respond_to?(:model_name) ? model_name : name - decorator_name = "#{prefix}Decorator" - decorator_name.constantize - rescue NameError => error - if superclass.respond_to?(:decorator_class) - superclass.decorator_class - else - raise unless error.missing_name?(decorator_name) - raise Draper::UninferrableDecoratorError.new(self) - end - end - - # Compares with possibly-decorated objects. - # - # @return [Boolean] - def ===(other) - super || (other.respond_to?(:object) && super(other.object)) - end - - end - - end -end diff --git a/spec/draper/decoratable/equality_spec.rb b/spec/draper/decoratable/equality_spec.rb deleted file mode 100644 index c2d9662..0000000 --- a/spec/draper/decoratable/equality_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'support/shared_examples/decoratable_equality' - -module Draper - describe Decoratable::Equality do - describe "#==" do - it_behaves_like "decoration-aware #==", Object.new.extend(Decoratable::Equality) - end - end -end diff --git a/spec/draper/decoratable_spec.rb b/spec/draper/decoratable_spec.rb deleted file mode 100644 index 6f608f4..0000000 --- a/spec/draper/decoratable_spec.rb +++ /dev/null @@ -1,202 +0,0 @@ -require 'spec_helper' -require 'support/shared_examples/decoratable_equality' - -module Draper - describe Decoratable do - - describe "#decorate" do - it "returns a decorator for self" do - product = Product.new - decorator = product.decorate - - expect(decorator).to be_a ProductDecorator - expect(decorator.object).to be product - end - - it "accepts context" do - context = {some: "context"} - decorator = Product.new.decorate(context: context) - - expect(decorator.context).to be context - end - - it "uses the #decorator_class" do - product = Product.new - product.stub decorator_class: OtherDecorator - - expect(product.decorate).to be_an_instance_of OtherDecorator - end - end - - describe "#applied_decorators" do - it "returns an empty list" do - expect(Product.new.applied_decorators).to eq [] - end - end - - describe "#decorated_with?" do - it "returns false" do - expect(Product.new).not_to be_decorated_with Decorator - end - end - - describe "#decorated?" do - it "returns false" do - expect(Product.new).not_to be_decorated - end - end - - describe "#decorator_class?" do - it "returns true for decoratable model" do - expect(Product.new.decorator_class?).to be_truthy - end - - it "returns false for non-decoratable model" do - expect(Model.new.decorator_class?).to be_falsey - end - end - - describe ".decorator_class?" do - it "returns true for decoratable model" do - expect(Product.decorator_class?).to be_truthy - end - - it "returns false for non-decoratable model" do - expect(Model.decorator_class?).to be_falsey - end - end - - describe "#decorator_class" do - it "delegates to .decorator_class" do - product = Product.new - - Product.should_receive(:decorator_class).and_return(:some_decorator) - expect(product.decorator_class).to be :some_decorator - end - end - - describe "#==" do - it_behaves_like "decoration-aware #==", Product.new - end - - describe "#===" do - it "is true when #== is true" do - product = Product.new - - product.should_receive(:==).and_return(true) - expect(product === :anything).to be_truthy - end - - it "is false when #== is false" do - product = Product.new - - product.should_receive(:==).and_return(false) - expect(product === :anything).to be_falsey - end - end - - describe ".====" do - it "is true for an instance" do - expect(Product === Product.new).to be_truthy - end - - it "is true for a derived instance" do - expect(Product === Class.new(Product).new).to be_truthy - end - - it "is false for an unrelated instance" do - expect(Product === Model.new).to be_falsey - end - - it "is true for a decorated instance" do - decorator = double(object: Product.new) - - expect(Product === decorator).to be_truthy - end - - it "is true for a decorated derived instance" do - decorator = double(object: Class.new(Product).new) - - expect(Product === decorator).to be_truthy - end - - it "is false for a decorated unrelated instance" do - decorator = double(object: Model.new) - - expect(Product === decorator).to be_falsey - end - end - - describe ".decorate" do - let(:scoping_method) { Rails::VERSION::MAJOR >= 4 ? :all : :scoped } - - it "calls #decorate_collection on .decorator_class" do - scoped = [Product.new] - Product.stub scoping_method => scoped - - Product.decorator_class.should_receive(:decorate_collection).with(scoped, with: nil).and_return(:decorated_collection) - expect(Product.decorate).to be :decorated_collection - end - - it "accepts options" do - options = {with: ProductDecorator, context: {some: "context"}} - Product.stub scoping_method => [] - - Product.decorator_class.should_receive(:decorate_collection).with([], options) - Product.decorate(options) - end - end - - describe ".decorator_class" do - context "for classes" do - it "infers the decorator from the class" do - expect(Product.decorator_class).to be ProductDecorator - end - - context "without a decorator on its own" do - it "infers the decorator from a superclass" do - expect(SpecialProduct.decorator_class).to be ProductDecorator - end - end - end - - context "for ActiveModel classes" do - it "infers the decorator from the model name" do - allow(Product).to receive(:model_name){"Other"} - - expect(Product.decorator_class).to be OtherDecorator - end - end - - context "in a namespace" do - context "for classes" do - it "infers the decorator from the class" do - expect(Namespaced::Product.decorator_class).to be Namespaced::ProductDecorator - end - end - - context "for ActiveModel classes" do - it "infers the decorator from the model name" do - Namespaced::Product.stub(:model_name).and_return("Namespaced::Other") - - expect(Namespaced::Product.decorator_class).to be Namespaced::OtherDecorator - end - end - end - - context "when the decorator can't be inferred" do - it "throws an UninferrableDecoratorError" do - expect{Model.decorator_class}.to raise_error UninferrableDecoratorError - end - end - - context "when an unrelated NameError is thrown" do - it "re-raises that error" do - String.any_instance.stub(:constantize) { Draper::Base } - expect{Product.decorator_class}.to raise_error NameError, /Draper::Base/ - end - end - end - - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index df3aad9..2862591 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -12,7 +12,7 @@ RSpec.configure do |config| end end -class Model; include Draper::Decoratable; end +class Model; end class Product < Model; end class SpecialProduct < Product; end