From c70045aeac922b9c72a375b095bd2c61f32ae367 Mon Sep 17 00:00:00 2001 From: Jeff Casimir Date: Sat, 23 Jul 2011 10:15:53 -0700 Subject: [PATCH] Clean up protections with regards to method_missing in AR circumventing denied methods --- lib/draper/base.rb | 2 +- spec/base_spec.rb | 33 +++++++++++++++------------ spec/samples/active_record.rb | 7 ++++++ spec/samples/decorator_with_denies.rb | 2 +- spec/samples/product.rb | 21 +++++++++++++++++ spec/samples/product_decorator.rb | 14 ------------ 6 files changed, 48 insertions(+), 31 deletions(-) create mode 100644 spec/samples/active_record.rb create mode 100644 spec/samples/product.rb diff --git a/lib/draper/base.rb b/lib/draper/base.rb index bd4b836..8b6d1d2 100644 --- a/lib/draper/base.rb +++ b/lib/draper/base.rb @@ -4,7 +4,7 @@ module Draper class_attribute :denied, :allowed, :model_class attr_accessor :model - DEFAULT_DENIED = Object.new.methods + DEFAULT_DENIED = Object.new.methods << :method_missing FORCED_PROXY = [:to_param] self.denied = DEFAULT_DENIED diff --git a/spec/base_spec.rb b/spec/base_spec.rb index 7d1cb2a..2c630bd 100644 --- a/spec/base_spec.rb +++ b/spec/base_spec.rb @@ -19,9 +19,11 @@ describe Draper::Base do end context("selecting methods") do - it "echos the methods of the wrapped class" do + it "echos the methods of the wrapped class except default exclusions" do source.methods.each do |method| - subject.should respond_to(method) + unless Draper::Base::DEFAULT_DENIED.include?(method) + subject.should respond_to(method) + end end end @@ -74,19 +76,24 @@ describe Draper::Base do end end - describe "a sample usage with denies" do - before(:all) do - end - + describe "a sample usage with denies" do let(:subject_with_denies){ DecoratorWithDenies.new(source) } + it "should proxy methods not listed in denies" do + subject_with_denies.should respond_to(:hello_world) + end + it "should not echo methods specified with denies" do - subject_with_denies.should_not respond_to(:upcase) + subject_with_denies.should_not respond_to(:goodnight_moon) end it "should not clobber other decorators' methods" do subject.should respond_to(:hello_world) end + + it "should not allow method_missing to circumvent a deny" do + expect{subject_with_denies.title}.to raise_error(NoMethodError) + end end describe "a sample usage with allows" do @@ -116,15 +123,15 @@ describe Draper::Base do let(:using_allows_then_denies){ class DecoratorWithAllowsAndDenies < Draper::Base - allows :upcase - denies :downcase + allows :hello_world + denies :goodnight_moon end } let(:using_denies_then_allows){ class DecoratorWithDeniesAndAllows < Draper::Base - denies :downcase - allows :upcase + denies :goodnight_moon + allows :hello_world end } @@ -163,9 +170,5 @@ describe Draper::Base do it "should be able to use the pluralize helper" do decorator.sample_truncate.should == "Once..." end - - it "should nullify method_missing to prevent AR from being cute" do - pending("How to test this without AR? Ugh.") - end end end \ No newline at end of file diff --git a/spec/samples/active_record.rb b/spec/samples/active_record.rb new file mode 100644 index 0000000..9b561b6 --- /dev/null +++ b/spec/samples/active_record.rb @@ -0,0 +1,7 @@ +module ActiveRecord + class Base + def method_missing(name, *args) + name + end + end +end \ No newline at end of file diff --git a/spec/samples/decorator_with_denies.rb b/spec/samples/decorator_with_denies.rb index 1bdbd8b..aa831c7 100644 --- a/spec/samples/decorator_with_denies.rb +++ b/spec/samples/decorator_with_denies.rb @@ -1,3 +1,3 @@ class DecoratorWithDenies < Draper::Base - denies :upcase + denies :goodnight_moon, :title end diff --git a/spec/samples/product.rb b/spec/samples/product.rb new file mode 100644 index 0000000..fea85c1 --- /dev/null +++ b/spec/samples/product.rb @@ -0,0 +1,21 @@ +class Product < ActiveRecord::Base + def self.find(id) + return Product.new + end + + def hello_world + "Hello, World" + end + + def goodnight_moon + "Goodnight, Moon" + end + + def title + "Sample Title" + end + + def block + yield + end +end \ No newline at end of file diff --git a/spec/samples/product_decorator.rb b/spec/samples/product_decorator.rb index 66bbae6..f731419 100644 --- a/spec/samples/product_decorator.rb +++ b/spec/samples/product_decorator.rb @@ -1,17 +1,3 @@ -class Product - def self.find(id) - return Product.new - end - - def hello_world - "Hello, World" - end - - def block - yield - end -end - class ProductDecorator < Draper::Base decorates :product end