diff options
Diffstat (limited to 'actionview/lib/action_view/rendering.rb')
-rw-r--r-- | actionview/lib/action_view/rendering.rb | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/actionview/lib/action_view/rendering.rb b/actionview/lib/action_view/rendering.rb new file mode 100644 index 0000000000..cb4327cf16 --- /dev/null +++ b/actionview/lib/action_view/rendering.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +require "action_view/view_paths" + +module ActionView + # This is a class to fix I18n global state. Whenever you provide I18n.locale during a request, + # it will trigger the lookup_context and consequently expire the cache. + class I18nProxy < ::I18n::Config #:nodoc: + attr_reader :original_config, :lookup_context + + def initialize(original_config, lookup_context) + original_config = original_config.original_config if original_config.respond_to?(:original_config) + @original_config, @lookup_context = original_config, lookup_context + end + + def locale + @original_config.locale + end + + def locale=(value) + @lookup_context.locale = value + end + end + + module Rendering + extend ActiveSupport::Concern + include ActionView::ViewPaths + + # Overwrite process to setup I18n proxy. + def process(*) #:nodoc: + old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context) + super + ensure + I18n.config = old_config + end + + module ClassMethods + def view_context_class + @view_context_class ||= begin + supports_path = supports_path? + routes = respond_to?(:_routes) && _routes + helpers = respond_to?(:_helpers) && _helpers + + Class.new(ActionView::Base) do + if routes + include routes.url_helpers(supports_path) + include routes.mounted_helpers + end + + if helpers + include helpers + end + end + end + end + end + + attr_internal_writer :view_context_class + + def view_context_class + @_view_context_class ||= self.class.view_context_class + end + + # An instance of a view class. The default view class is ActionView::Base. + # + # The view class must have the following methods: + # + # * <tt>View.new(lookup_context, assigns, controller)</tt> — Create a new + # ActionView instance for a controller and we can also pass the arguments. + # + # * <tt>View#render(option)</tt> — Returns String with the rendered template. + # + # Override this method in a module to change the default behavior. + def view_context + view_context_class.new(view_renderer, view_assigns, self) + end + + # Returns an object that is able to render templates. + def view_renderer # :nodoc: + @_view_renderer ||= ActionView::Renderer.new(lookup_context) + end + + def render_to_body(options = {}) + _process_options(options) + _render_template(options) + end + + def rendered_format + Template::Types[lookup_context.rendered_format] + end + + private + + # Find and render a template based on the options given. + def _render_template(options) + variant = options.delete(:variant) + assigns = options.delete(:assigns) + context = view_context + + context.assign assigns if assigns + lookup_context.rendered_format = nil if options[:formats] + lookup_context.variants = variant if variant + + view_renderer.render(context, options) + end + + # Assign the rendered format to look up context. + def _process_format(format) + super + lookup_context.formats = [format.to_sym] + lookup_context.rendered_format = lookup_context.formats.first + end + + # Normalize args by converting render "foo" to render :action => "foo" and + # render "foo/bar" to render :template => "foo/bar". + def _normalize_args(action = nil, options = {}) + options = super(action, options) + case action + when NilClass + when Hash + options = action + when String, Symbol + action = action.to_s + key = action.include?(?/) ? :template : :action + options[key] = action + else + if action.respond_to?(:permitted?) && action.permitted? + options = action + else + options[:partial] = action + end + end + + options + end + + # Normalize options. + def _normalize_options(options) + options = super(options) + if options[:partial] == true + options[:partial] = action_name + end + + if (options.keys & [:partial, :file, :template]).empty? + options[:prefixes] ||= _prefixes + end + + options[:template] ||= (options[:action] || action_name).to_s + options + end + end +end |