Monkeypatch ActionController::Base.

We need to be able to let draper get a copy of the view_context
no matter what happens. AC::Base doesn't really let us do that. So
we have to monkeypatch.

This was originally suggested in
https://github.com/jcasimir/draper/issues/124#issuecomment-6954291
by @rf-.

It appears to be the cleanest way to take care of this problem, and
shouldn't affect any other things, since we keep the exact same
semantics of view_context.

Theoretically:

Fixes #124
Fixes #109
This commit is contained in:
Steve Klabnik 2012-07-16 12:43:29 -04:00
parent e4319afdf3
commit 0b03d9c21e
9 changed files with 29 additions and 36 deletions

View File

@ -10,6 +10,7 @@ require 'draper/helper_support'
require 'draper/view_context'
require 'draper/decorated_enumerable_proxy'
require 'draper/railtie' if defined?(Rails)
require 'draper/action_controller/base'
# Test Support
require 'draper/test/rspec_integration' if defined?(RSpec) and RSpec.respond_to?(:configure)

View File

@ -0,0 +1,9 @@
module DraperViewContext
def view_context
super.tap do |context|
Draper::ViewContext.current = context
end
end
end
ApplicationController.send(:include, DraperViewContext)

View File

@ -2,7 +2,6 @@ module Draper
class System
def self.setup(component)
component.class_eval do
include Draper::ViewContextFilter
extend Draper::HelperSupport unless defined?(::ActionMailer) && self.is_a?(::ActionMailer::Base)
end
end

View File

@ -2,7 +2,7 @@ module Draper
module ViewContext
def self.infect!(context)
context.instance_eval do
ApplicationController.new.set_current_view_context
ApplicationController.new.view_context
Draper::ViewContext.current.controller.request ||= ActionController::TestRequest.new
Draper::ViewContext.current.request ||= Draper::ViewContext.current.controller.request
Draper::ViewContext.current.params ||= {}

View File

@ -8,14 +8,4 @@ module Draper
Thread.current[:current_view_context] = input
end
end
module ViewContextFilter
def set_current_view_context
Draper::ViewContext.current = self.view_context
end
def self.included(source)
source.send(:before_filter, :set_current_view_context) if source.respond_to?(:before_filter)
end
end
end

View File

@ -1,7 +1,7 @@
require 'spec_helper'
describe Draper::Base do
before(:each){ ApplicationController.new.set_current_view_context }
before(:each){ ApplicationController.new.view_context }
subject{ Decorator.new(source) }
let(:source){ Product.new }
let(:non_active_model_source){ NonActiveModelProduct.new }

View File

@ -5,19 +5,6 @@ describe Draper::ViewContext do
let(:app_controller) { ApplicationController }
let(:app_controller_instance) { app_controller.new }
it "implements #set_current_view_context" do
app_controller_instance.should respond_to(:set_current_view_context)
end
it "calls #before_filter with #set_current_view_context" do
app_controller.before_filters.should include(:set_current_view_context)
end
it "raises an exception if the view_context is fetched without being set" do
Draper::ViewContext.current = nil
expect {app_controller.current_view_context}.should raise_exception(Exception)
end
it "provides a method to create a view context while testing" do
Draper::ViewContext.should respond_to(:infect!)
end

View File

@ -2,11 +2,13 @@ require 'bundler/setup'
require 'ammeter/init'
require 'rails'
require 'action_view'
require './spec/support/samples/application_controller'
Bundler.require
require './spec/support/samples/active_model'
require './spec/support/samples/active_record'
require './spec/support/samples/application_controller'
require './spec/support/samples/application_helper'
require './spec/support/samples/decorator'
require './spec/support/samples/decorator_with_allows'
@ -24,3 +26,9 @@ require './spec/support/samples/some_thing'
require './spec/support/samples/some_thing_decorator'
require './spec/support/samples/widget'
require './spec/support/samples/widget_decorator'
module ActionController
class Base
Draper::System.setup(self)
end
end

View File

@ -10,7 +10,14 @@ module ActionController
@@before_filters << name
end
Draper::System.setup(self)
def view_context
# puts "zomg view context"
@view_context ||= ApplicationController
end
def view_context=(input)
@view_context = input
end
end
end
@ -20,14 +27,6 @@ class ApplicationController < ActionController::Base
extend ActionView::Helpers::UrlHelper
extend ApplicationHelper
def view_context
@view_context ||= ApplicationController
end
def view_context=(input)
@view_context = input
end
def self.hello
"Hello!"
end