Add support for custom default controller configuration (#788)

* Add configure functionality to allow customizing the default.

* Add configuration module and tests.

* Add documentation to the README.md

* Skip tests that only fail when whole suite is ran.

* Fix the double leaking by re-writing the test that caused the issue.

* Clean up railtie - Exract out method, Remove unnecessary compatibility.

* Add new functionality to the dummy app to increase test coverage.
This commit is contained in:
Cliff Braton 2017-03-31 09:05:15 -05:00 committed by GitHub
parent 2e6f741a63
commit ff36bd81ad
13 changed files with 85 additions and 31 deletions

View File

@ -368,6 +368,18 @@ you'll have access to an ArticleDecorator object instead. In your controller you
can continue to use the `@article` instance variable to manipulate the model -
for example, `@article.comments.build` to add a new blank comment for a form.
## Configuration
Draper works out the box well, but also provides a hook for you to configure its
default functionality. For example, Draper assumes you have a base `ApplicationController`.
If your base controller is named something different (e.g. `BaseController`),
you can tell Draper to use it by adding the following to an initializer:
```ruby
Draper.configure do |config|
config.default_controller = BaseController
end
```
## Testing
Draper supports RSpec, MiniTest::Rails, and Test::Unit, and will add the

View File

@ -9,6 +9,7 @@ require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/name_error'
require 'draper/version'
require 'draper/configuration'
require 'draper/view_helpers'
require 'draper/delegation'
require 'draper/automatic_delegation'
@ -27,6 +28,8 @@ require 'draper/decorates_assigned'
require 'draper/railtie' if defined?(Rails)
module Draper
extend Draper::Configuration
def self.setup_action_controller(base)
base.class_eval do
include Draper::ViewContext

View File

@ -0,0 +1,15 @@
module Draper
module Configuration
def configure
yield self
end
def default_controller
@@default_controller ||= ApplicationController
end
def default_controller=(controller)
@@default_controller = controller
end
end
end

View File

@ -3,8 +3,6 @@ require 'rails/railtie'
module ActiveModel
class Railtie < Rails::Railtie
generators do |app|
app ||= Rails.application # Rails 3.0.x does not yield `app`
Rails::Generators.configure! app.config.generators
require_relative '../generators/controller_override'
end
@ -13,7 +11,6 @@ end
module Draper
class Railtie < Rails::Railtie
config.after_initialize do |app|
app.config.paths.add 'app/decorators', eager_load: true
@ -23,19 +20,19 @@ module Draper
end
end
initializer "draper.setup_action_controller" do |app|
initializer 'draper.setup_action_controller' do
ActiveSupport.on_load :action_controller do
Draper.setup_action_controller self
end
end
initializer "draper.setup_action_mailer" do |app|
initializer 'draper.setup_action_mailer' do
ActiveSupport.on_load :action_mailer do
Draper.setup_action_mailer self
end
end
initializer "draper.setup_orm" do |app|
initializer 'draper.setup_orm' do
[:active_record, :mongoid].each do |orm|
ActiveSupport.on_load orm do
Draper.setup_orm self
@ -43,26 +40,22 @@ module Draper
end
end
initializer "draper.minitest-rails_integration" do |app|
initializer 'draper.minitest-rails_integration' do
ActiveSupport.on_load :minitest do
require "draper/test/minitest_integration"
require 'draper/test/minitest_integration'
end
end
console do
def initialize_view_context
require 'action_controller/test_case'
ApplicationController.new.view_context
Draper.default_controller.new.view_context
Draper::ViewContext.build
end
runner do
require 'action_controller/test_case'
ApplicationController.new.view_context
Draper::ViewContext.build
end
console { initialize_view_context }
rake_tasks do
Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
end
runner { initialize_view_context }
rake_tasks { Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |f| load f } }
end
end

View File

@ -37,7 +37,8 @@ module Draper
attr_reader :block
def controller
(Draper::ViewContext.controller || ApplicationController.new).tap do |controller|
Draper::ViewContext.controller ||= Draper.default_controller.new
Draper::ViewContext.controller.tap do |controller|
controller.request ||= new_test_request controller if defined?(ActionController::TestRequest)
end
end

View File

@ -0,0 +1,25 @@
require 'spec_helper'
module Draper
RSpec.describe Configuration do
it 'yields Draper on configure' do
Draper.configure { |config| expect(config).to be Draper }
end
it 'defaults default_controller to ApplicationController' do
expect(Draper.default_controller).to be ApplicationController
end
it 'allows customizing default_controller through configure' do
default = Draper.default_controller
Draper.configure do |config|
config.default_controller = CustomController
end
expect(Draper.default_controller).to be CustomController
Draper.default_controller = default
end
end
end

View File

@ -23,11 +23,10 @@ module Draper
context "when a current controller is not set" do
it "uses ApplicationController" do
view_context = fake_view_context
stub_const "ApplicationController", double(new: fake_controller(view_context))
strategy = ViewContext::BuildStrategy::Full.new
expect(strategy.call).to be view_context
expect(Draper::ViewContext.controller).to be_nil
view_context = ViewContext::BuildStrategy::Full.new.call
expect(view_context.controller).to eq Draper::ViewContext.controller
expect(view_context.controller).to be_an ApplicationController
end
end

View File

@ -1,4 +0,0 @@
class ApplicationController < ActionController::Base
include LocalizedUrls
protect_from_forgery
end

View File

@ -0,0 +1,4 @@
class BaseController < ActionController::Base
include LocalizedUrls
protect_from_forgery
end

View File

@ -1,4 +1,4 @@
class PostsController < ApplicationController
class PostsController < BaseController
decorates_assigned :post
def show

View File

@ -0,0 +1,3 @@
Draper.configure do |config|
config.default_controller = BaseController
end

View File

@ -58,7 +58,7 @@ describe PostDecorator do
expect(xml).to have_css "post > updated-at", text: "overridden"
end
it "uses a test view context from ApplicationController" do
expect(Draper::ViewContext.current.controller).to be_an ApplicationController
it "uses a test view context from BaseController" do
expect(Draper::ViewContext.current.controller).to be_an BaseController
end
end

View File

@ -30,6 +30,9 @@ module Namespaced
class OtherDecorator < Draper::Decorator; end
end
ApplicationController = Class.new(ActionController::Base)
CustomController = Class.new(ActionController::Base)
# After each example, revert changes made to the class
def protect_class(klass)
before { stub_const klass.name, Class.new(klass) }