aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
authorPiotr Sarnacki <drogus@gmail.com>2013-08-26 03:07:30 -0700
committerPiotr Sarnacki <drogus@gmail.com>2013-08-26 03:07:30 -0700
commitc19958015fac7b50f8dedbdf17991c00d6b8bbd4 (patch)
tree42431a33fd65c954b1242b8ff6116163c9969924 /actionpack/lib/action_controller
parent27dc4fa28ee098d70a11829ad5fa4af0c54e880b (diff)
parent0d43df7ebf7587f032e3b16c153bf35746878c46 (diff)
downloadrails-c19958015fac7b50f8dedbdf17991c00d6b8bbd4.tar.gz
rails-c19958015fac7b50f8dedbdf17991c00d6b8bbd4.tar.bz2
rails-c19958015fac7b50f8dedbdf17991c00d6b8bbd4.zip
Merge pull request #11396 from strzalek/extract_renderers
Remove dependency on Action View from Action Pack This set of changes removes the need of using Action View with Action Pack. Now you may use controllers without Action View, by rendering `:text` response or alternatively you can plug in your own rendering logic. This is especially handy when you're just dealing with APIs and don't need to include entire Action View just to render simple JSON responses.
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r--actionpack/lib/action_controller/base.rb18
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb42
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb38
-rw-r--r--actionpack/lib/action_controller/railtie.rb1
4 files changed, 70 insertions, 29 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 67d261db77..9941c06201 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -2,6 +2,21 @@ require "action_controller/log_subscriber"
require "action_controller/metal/params_wrapper"
module ActionController
+ # The <tt>metal</tt> anonymous class was introduced to solve issue with including modules in <tt>ActionController::Base</tt>.
+ # Modules needes to be included in particluar order. First wee need to have <tt>AbstractController::Rendering</tt> included,
+ # next we should include actuall implementation which would be for example <tt>ActionView::Rendering</tt> and after that
+ # <tt>ActionController::Rendering</tt>. This order must be preserved and as we want to have middle module included dynamicaly
+ # <tt>metal</tt> class was introduced. It has <tt>AbstractController::Rendering</tt> included and is parent class of
+ # <tt>ActionController::Base</tt> which includes <tt>ActionController::Rendering</tt>. If we include <tt>ActionView::Rendering</tt>
+ # beetween them to perserve the required order, we can simply do this by:
+ #
+ # ActionController::Base.superclass.send(:include, ActionView::Rendering)
+ #
+ metal = Class.new(Metal) do
+ include AbstractController::Rendering
+ include ActionController::BasicRendering
+ end
+
# Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
# on request and then either it renders a template or redirects to another action. An action is defined as a public method
# on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
@@ -160,7 +175,7 @@ module ActionController
# render action: "overthere" # won't be called if monkeys is nil
# end
#
- class Base < Metal
+ class Base < metal
abstract!
# We document the request and response methods here because albeit they are
@@ -200,7 +215,6 @@ module ActionController
end
MODULES = [
- AbstractController::Layouts,
AbstractController::Translation,
AbstractController::AssetPaths,
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index bea6b88f91..21224b9c3b 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -1,8 +1,38 @@
module ActionController
- module Rendering
+ # Basic rendering implements the most minimal rendering layer.
+ # It only supports rendering :text and :nothing. Passing any other option will
+ # result in `UnsupportedOperationError` exception. For more functionality like
+ # different formats, layouts etc. you should use `ActionView` gem.
+ module BasicRendering
extend ActiveSupport::Concern
- include AbstractController::Rendering
+ # Render text or nothing (empty string) to response_body
+ # :api: public
+ def render(*args, &block)
+ super(*args, &block)
+ opts = args.first
+ if opts.has_key?(:text) && opts[:text].present?
+ self.response_body = opts[:text]
+ elsif opts.has_key?(:nothing) && opts[:nothing]
+ self.response_body = " "
+ else
+ raise UnsupportedOperationError
+ end
+ end
+
+ def rendered_format
+ Mime::TEXT
+ end
+
+ class UnsupportedOperationError < StandardError
+ def initialize
+ super "Unsupported render operation. BasicRendering supports only :text and :nothing options. For more, you need to include ActionView."
+ end
+ end
+ end
+
+ module Rendering
+ extend ActiveSupport::Concern
# Before processing, set the request formats in current controller formats.
def process_action(*) #:nodoc:
@@ -12,17 +42,17 @@ module ActionController
# Check for double render errors and set the content_type after rendering.
def render(*args) #:nodoc:
- raise ::AbstractController::DoubleRenderError if response_body
+ raise ::AbstractController::DoubleRenderError if self.response_body
super
- self.content_type ||= Mime[lookup_context.rendered_format].to_s
- response_body
+ self.content_type ||= rendered_format.to_s
+ self.response_body
end
# Overwrite render_to_string because body can now be set to a rack body.
def render_to_string(*)
if self.response_body = super
string = ""
- response_body.each { |r| string << r }
+ self.response_body.each { |r| string << r }
string
end
ensure
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 73e9b5660d..62d5931b45 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -193,31 +193,29 @@ module ActionController #:nodoc:
module Streaming
extend ActiveSupport::Concern
- include AbstractController::Rendering
-
protected
- # Set proper cache control and transfer encoding when streaming
- def _process_options(options) #:nodoc:
- super
- if options[:stream]
- if env["HTTP_VERSION"] == "HTTP/1.0"
- options.delete(:stream)
- else
- headers["Cache-Control"] ||= "no-cache"
- headers["Transfer-Encoding"] = "chunked"
- headers.delete("Content-Length")
+ # Set proper cache control and transfer encoding when streaming
+ def _process_options(options) #:nodoc:
+ super
+ if options[:stream]
+ if env["HTTP_VERSION"] == "HTTP/1.0"
+ options.delete(:stream)
+ else
+ headers["Cache-Control"] ||= "no-cache"
+ headers["Transfer-Encoding"] = "chunked"
+ headers.delete("Content-Length")
+ end
end
end
- end
- # Call render_body if we are streaming instead of usual +render+.
- def _render_template(options) #:nodoc:
- if options.delete(:stream)
- Rack::Chunked::Body.new view_renderer.render_body(view_context, options)
- else
- super
+ # Call render_body if we are streaming instead of usual +render+.
+ def _render_template(options) #:nodoc:
+ if options.delete(:stream)
+ Rack::Chunked::Body.new view_renderer.render_body(view_context, options)
+ else
+ super
+ end
end
- end
end
end
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index 5379547c57..0833e65d23 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -1,7 +1,6 @@
require "rails"
require "action_controller"
require "action_dispatch/railtie"
-require "action_view/railtie"
require "abstract_controller/railties/routes_helpers"
require "action_controller/railties/helpers"