diff --git a/lib/draper/base.rb b/lib/draper/base.rb index 1dee812..8924ad3 100644 --- a/lib/draper/base.rb +++ b/lib/draper/base.rb @@ -2,7 +2,7 @@ module Draper class Base require 'active_support/core_ext/class/attribute' class_attribute :denied, :allowed, :model_class - attr_accessor :context, :model + attr_accessor :model, :options DEFAULT_DENIED = Object.new.methods << :method_missing FORCED_PROXY = [:to_param, :id] @@ -23,7 +23,7 @@ module Draper input.inspect # forces evaluation of a lazy query from AR self.class.model_class = input.class if model_class.nil? @model = input - self.context = options.fetch(:context, {}) + self.options = options end # Proxies to the class specified by `decorates` to automatically @@ -119,7 +119,10 @@ module Draper # @param [Object] instance(s) to wrap # @param [Hash] options (optional) def self.decorate(input, options = {}) - if input.respond_to?(:each) + if input.instance_of?(self) + input.options = options unless options.empty? + return input + elsif input.respond_to?(:each) Draper::DecoratedEnumerableProxy.new(input, self, options) elsif options[:infer] input.decorator(options) @@ -214,6 +217,14 @@ module Draper super || model_class.respond_to?(method) end + def context + options.fetch(:context, {}) + end + + def context=(input) + options[:context] = input + end + private def allow?(method) (!allowed? || allowed.include?(method) || FORCED_PROXY.include?(method)) && !denied.include?(method) diff --git a/spec/draper/base_spec.rb b/spec/draper/base_spec.rb index 02fcc24..e503e47 100644 --- a/spec/draper/base_spec.rb +++ b/spec/draper/base_spec.rb @@ -224,6 +224,25 @@ describe Draper::Base do let(:source) { Product.new } it { should be_instance_of(Draper::Base) } + + context "when the input is already decorated" do + it "does not perform double-decoration" do + decorated = ProductDecorator.decorate(source) + ProductDecorator.decorate(decorated).object_id.should == decorated.object_id + end + + it "overwrites options with provided options" do + first_run = ProductDecorator.decorate(source, :context => {:role => :user}) + second_run = ProductDecorator.decorate(first_run, :context => {:role => :admin}) + second_run.context[:role].should == :admin + end + + it "leaves existing options if none are supplied" do + first_run = ProductDecorator.decorate(source, :context => {:role => :user}) + second_run = ProductDecorator.decorate(first_run) + second_run.context[:role].should == :user + end + end end end @@ -246,6 +265,14 @@ describe Draper::Base do its(:context) { should eq(context) } end end + + context "with options" do + let(:options) {{ :more => "settings" }} + + subject { Draper::Base.decorate(source, options ) } + + its(:options) { should eq(options) } + end context "does not infer collections by default" do subject { Draper::Base.decorate(source).to_ary }