From 8599e21e2ffb6e22ff6a69c71b28a96df80e0836 Mon Sep 17 00:00:00 2001 From: Andrew Haines Date: Sun, 14 Oct 2012 23:01:15 +0100 Subject: [PATCH] Extract helper proxy --- lib/draper.rb | 1 + lib/draper/decorator.rb | 34 +++++++--------------------- lib/draper/helper_proxy.rb | 16 +++++++++++++ spec/draper/decorator_spec.rb | 39 ++++++++++++++++++-------------- spec/draper/helper_proxy_spec.rb | 12 ++++++++++ 5 files changed, 59 insertions(+), 43 deletions(-) create mode 100644 lib/draper/helper_proxy.rb create mode 100644 spec/draper/helper_proxy_spec.rb diff --git a/lib/draper.rb b/lib/draper.rb index deeae7b..d139b62 100644 --- a/lib/draper.rb +++ b/lib/draper.rb @@ -4,6 +4,7 @@ require 'draper/version' require 'draper/system' require 'draper/active_model_support' require 'draper/decorator' +require 'draper/helper_proxy' require 'draper/lazy_helpers' require 'draper/decoratable' require 'draper/security' diff --git a/lib/draper/decorator.rb b/lib/draper/decorator.rb index e65e9ed..02200fe 100755 --- a/lib/draper/decorator.rb +++ b/lib/draper/decorator.rb @@ -162,48 +162,30 @@ module Draper decorate(model_class.last, options) end - # Some helpers are private, for example html_escape... as a workaround - # we are wrapping the helpers in a delegator that passes the methods - # along through a send, which will ignore private/public distinctions - class HelpersWrapper - def initialize(helpers) - @helpers = helpers - end - - def method_missing(method, *args, &block) - @helpers.send(method, *args, &block) - end - - #needed for tests - def ==(other) - other.instance_variable_get(:@helpers) == @helpers - end - end - # Access the helpers proxy to call built-in and user-defined - # Rails helpers. Aliased to `.h` for convenience. + # Rails helpers. Aliased to `h` for convenience. # - # @return [Object] proxy + # @return [HelperProxy] the helpers proxy def helpers - @helpers ||= HelpersWrapper.new self.class.helpers + self.class.helpers end alias :h :helpers # Localize is something that's used quite often. Even though # it's available through helpers, that's annoying. Aliased - # to `.l` for convenience. - def localize(object, options = {}) - self.class.helpers.localize(object, options) + # to `l` for convenience. + def localize(*args) + helpers.localize(*args) end alias :l :localize # Access the helpers proxy to call built-in and user-defined # Rails helpers from a class context. # - # @return [Object] proxy + # @return [HelperProxy] the helpers proxy class << self def helpers - Draper::ViewContext.current + @helpers ||= HelperProxy.new end alias :h :helpers end diff --git a/lib/draper/helper_proxy.rb b/lib/draper/helper_proxy.rb new file mode 100644 index 0000000..9a7edf7 --- /dev/null +++ b/lib/draper/helper_proxy.rb @@ -0,0 +1,16 @@ +module Draper + class HelperProxy + # Some helpers are private, for example html_escape... as a workaround + # we are wrapping the helpers in a delegator that passes the methods + # along through a send, which will ignore private/public distinctions + def method_missing(method, *args, &block) + view_context.send(method, *args, &block) + end + + private + + def view_context + Draper::ViewContext.current + end + end +end diff --git a/spec/draper/decorator_spec.rb b/spec/draper/decorator_spec.rb index cf56ca5..1e62aa2 100755 --- a/spec/draper/decorator_spec.rb +++ b/spec/draper/decorator_spec.rb @@ -20,13 +20,13 @@ describe Draper::Decorator do end end - context(".helpers") do - it "have a valid view_context" do - subject.helpers.should be + describe "#helpers" do + it "returns a HelperProxy" do + subject.helpers.should be_a Draper::HelperProxy end - it "is aliased to .h" do - subject.h.should == subject.helpers + it "is aliased to #h" do + subject.h.should be subject.helpers end it "initializes the wrapper only once" do @@ -37,13 +37,25 @@ describe Draper::Decorator do end end - context("#helpers") do - it "have a valid view_context" do - Decorator.helpers.should be + describe "#localize" do + before { subject.helpers.should_receive(:localize).with(:an_object, {some: "options"}) } + + it "delegates to helpers" do + subject.localize(:an_object, some: "options") end - it "is aliased to #h" do - Decorator.h.should == Decorator.helpers + it "is aliased to #l" do + subject.l(:an_object, some: "options") + end + end + + describe ".helpers" do + it "returns a HelperProxy" do + Decorator.helpers.should be_a Draper::HelperProxy + end + + it "is aliased to .h" do + Decorator.h.should be Decorator.helpers end end @@ -673,13 +685,6 @@ describe Draper::Decorator do decorator.sample_truncate.should == "Once..." end - it "is able to use l rather than helpers.l" do - now = Time.now - helper_proxy = decorator.helpers.instance_variable_get(:@helpers) - helper_proxy.should_receive(:localize).with(now, :format => :long) - decorator.l now, :format => :long - end - it "is able to access html_escape, a private method" do decorator.sample_html_escaped_text.should == '<script>danger</script>' end diff --git a/spec/draper/helper_proxy_spec.rb b/spec/draper/helper_proxy_spec.rb new file mode 100644 index 0000000..7cf6be5 --- /dev/null +++ b/spec/draper/helper_proxy_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe Draper::HelperProxy do + subject(:helper_proxy) { Draper::HelperProxy.new } + let(:view_context) { Object.new } + before { helper_proxy.stub(:view_context).and_return(view_context) } + + it "proxies methods to the view context" do + view_context.should_receive(:foo).with("bar") + helper_proxy.foo("bar") + end +end