Skip to content

Commit

Permalink
Extract helper proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
haines committed Oct 14, 2012
1 parent 96db1d0 commit 8599e21
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 43 deletions.
1 change: 1 addition & 0 deletions lib/draper.rb
Expand Up @@ -4,6 +4,7 @@
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'
Expand Down
34 changes: 8 additions & 26 deletions lib/draper/decorator.rb
Expand Up @@ -162,48 +162,30 @@ def self.last(options = {})
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
Expand Down
16 changes: 16 additions & 0 deletions 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
39 changes: 22 additions & 17 deletions spec/draper/decorator_spec.rb
Expand Up @@ -20,13 +20,13 @@
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
Expand All @@ -37,13 +37,25 @@
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

Expand Down Expand Up @@ -673,13 +685,6 @@ module Paginator; def page_number; "magic_value"; end; end
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 == '&lt;script&gt;danger&lt;/script&gt;'
end
Expand Down
12 changes: 12 additions & 0 deletions 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

0 comments on commit 8599e21

Please sign in to comment.