From ee6e13f3da11b21f3966e009b681d05c65f79c9e Mon Sep 17 00:00:00 2001 From: brainopia Date: Thu, 15 Jan 2015 16:26:50 +0300 Subject: Add `ActionController::Metal#set_request!` Add `ActionController::Metal#set_request!` to set a request on controller instance without calling dispatch. --- actionpack/lib/action_controller/metal.rb | 8 ++++++-- actionpack/lib/action_controller/metal/rack_delegation.rb | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'actionpack/lib/action_controller') diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 993f8e150d..ae111e4951 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -190,11 +190,15 @@ module ActionController end def dispatch(name, request) #:nodoc: + set_request!(request) + process(name) + to_a + end + + def set_request!(request) #:nodoc: @_request = request @_env = request.env @_env['action_controller.instance'] = self - process(name) - to_a end def to_a #:nodoc: diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 545d4a7e6e..82054880e9 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -8,9 +8,9 @@ module ActionController delegate :headers, :status=, :location=, :content_type=, :status, :location, :content_type, :response_code, :to => "@_response" - def dispatch(action, request) + def set_request!(request) #:nodoc: + super set_response!(request) - super(action, request) end def response_body=(body) -- cgit v1.2.3 From 47b6fe06824893f9b0c4628e766f387956cabf22 Mon Sep 17 00:00:00 2001 From: brainopia Date: Thu, 15 Jan 2015 22:35:40 +0300 Subject: Add ActionController#build_with_env To have an easier way to setup a controller instance with custom environment --- actionpack/lib/action_controller/metal/rack_delegation.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'actionpack/lib/action_controller') diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 82054880e9..ae9d89cc8c 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -8,6 +8,12 @@ module ActionController delegate :headers, :status=, :location=, :content_type=, :status, :location, :content_type, :response_code, :to => "@_response" + module ClassMethods + def build_with_env(env = {}) #:nodoc: + new.tap { |c| c.set_request! ActionDispatch::Request.new(env) } + end + end + def set_request!(request) #:nodoc: super set_response!(request) -- cgit v1.2.3 From 801e399e42cab610860e307f2dd77c1edb6e1fac Mon Sep 17 00:00:00 2001 From: brainopia Date: Sun, 18 Jan 2015 03:06:10 +0300 Subject: Add ActionController::Renderer Render arbitrary templates outside of controller actions --- .../lib/action_controller/metal/rendering.rb | 8 ++ actionpack/lib/action_controller/renderer.rb | 103 +++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 actionpack/lib/action_controller/renderer.rb (limited to 'actionpack/lib/action_controller') diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 7bbff0450a..2370c607ed 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -4,6 +4,14 @@ module ActionController RENDER_FORMATS_IN_PRIORITY = [:body, :text, :plain, :html] + module ClassMethods + # Returns a renderer class (inherited from ActionController::Renderer) + # for the controller. + def renderer + @renderer ||= Renderer.for(self) + end + end + # Before processing, set the request formats in current controller formats. def process_action(*) #:nodoc: self.formats = request.formats.map(&:ref).compact diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb new file mode 100644 index 0000000000..a122954968 --- /dev/null +++ b/actionpack/lib/action_controller/renderer.rb @@ -0,0 +1,103 @@ +module ActionController + # ActionController::Renderer allows to render arbitrary templates + # without requirement of being in controller actions. + # + # You get a concrete renderer class by invoking ActionController::Base#renderer. + # For example, + # + # ApplicationController.renderer + # + # It allows you to call method #render directly. + # + # ApplicationController.renderer.render template: '...' + # + # You can use a shortcut on controller to replace previous example with: + # + # ApplicationController.render template: '...' + # + # #render method allows you to use any options as when rendering in controller. + # For example, + # + # FooController.render :action, locals: { ... }, assigns: { ... } + # + # The template will be rendered in a Rack environment which is accessible through + # ActionController::Renderer#env. You can set it up in two ways: + # + # * by changing renderer defaults, like + # + # ApplicationController.renderer.defaults # => hash with default Rack environment + # + # * by initializing an instance of renderer by passing it a custom environment. + # + # ApplicationController.renderer.new(method: 'post', https: true) + # + class Renderer + class_attribute :controller, :defaults + # Rack environment to render templates in. + attr_reader :env + + class << self + delegate :render, to: :new + + # Create a new renderer class for a specific controller class. + def for(controller) + Class.new self do + self.controller = controller + self.defaults = { + http_host: 'example.org', + https: false, + method: 'get', + script_name: '', + 'rack.input' => '' + } + end + end + end + + # Accepts a custom Rack environment to render templates in. + # It will be merged with ActionController::Renderer.defaults + def initialize(env = {}) + @env = normalize_keys(defaults).merge normalize_keys(env) + @env['action_dispatch.routes'] = controller._routes + end + + # Render templates with any options from ActionController::Base#render_to_string. + def render(*args) + raise 'missing controller' unless controller? + + instance = controller.build_with_env(env) + instance.render_to_string(*args) + end + + private + def normalize_keys(env) + env.dup.tap do |new_env| + convert_symbols! new_env + handle_method_key! new_env + handle_https_key! new_env + end + end + + def convert_symbols!(env) + env.keys.each do |key| + if key.is_a? Symbol + value = env.delete key + key = key.to_s.upcase + env[key] = value + end + end + end + + def handle_method_key!(env) + if method = env.delete('METHOD') + env['REQUEST_METHOD'] = method.upcase + end + end + + def handle_https_key!(env) + if env.has_key? 'HTTPS' + env['HTTPS'] = env['HTTPS'] ? 'on' : 'off' + end + end + end +end -- cgit v1.2.3 From 656628961c009524bd97ec5682b3dab3b850cb8a Mon Sep 17 00:00:00 2001 From: brainopia Date: Thu, 22 Jan 2015 00:23:22 +0300 Subject: Add ActionController::Base.render --- actionpack/lib/action_controller/metal/rendering.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'actionpack/lib/action_controller') diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 2370c607ed..2d15c39d88 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -5,6 +5,9 @@ module ActionController RENDER_FORMATS_IN_PRIORITY = [:body, :text, :plain, :html] module ClassMethods + # Documentation at ActionController::Renderer#render + delegate :render, to: :renderer + # Returns a renderer class (inherited from ActionController::Renderer) # for the controller. def renderer -- cgit v1.2.3