Reworked handling of options/context and resolved double-decoration

This commit is contained in:
Jeff Casimir 2012-01-16 21:22:59 -05:00
parent 81781988fa
commit d154059572
2 changed files with 41 additions and 3 deletions

View File

@ -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)

View File

@ -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 }