aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'actionview/lib/action_view/renderer')
-rw-r--r--actionview/lib/action_view/renderer/abstract_renderer.rb30
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb324
-rw-r--r--actionview/lib/action_view/renderer/streaming_template_renderer.rb88
-rw-r--r--actionview/lib/action_view/renderer/template_renderer.rb118
4 files changed, 280 insertions, 280 deletions
diff --git a/actionview/lib/action_view/renderer/abstract_renderer.rb b/actionview/lib/action_view/renderer/abstract_renderer.rb
index baff791987..3c85be49cd 100644
--- a/actionview/lib/action_view/renderer/abstract_renderer.rb
+++ b/actionview/lib/action_view/renderer/abstract_renderer.rb
@@ -27,27 +27,27 @@ module ActionView
protected
- def extract_details(options)
- @lookup_context.registered_details.each_with_object({}) do |key, details|
- value = options[key]
+ def extract_details(options)
+ @lookup_context.registered_details.each_with_object({}) do |key, details|
+ value = options[key]
- details[key] = Array(value) if value
+ details[key] = Array(value) if value
+ end
end
- end
- def instrument(name, **options)
- options[:identifier] ||= (@template && @template.identifier) || @path
+ def instrument(name, **options)
+ options[:identifier] ||= (@template && @template.identifier) || @path
- ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
- yield payload
+ ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
+ yield payload
+ end
end
- end
- def prepend_formats(formats)
- formats = Array(formats)
- return if formats.empty? || @lookup_context.html_fallback_for_js
+ def prepend_formats(formats)
+ formats = Array(formats)
+ return if formats.empty? || @lookup_context.html_fallback_for_js
- @lookup_context.formats = formats | @lookup_context.formats
- end
+ @lookup_context.formats = formats | @lookup_context.formats
+ end
end
end
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index 114e4092af..1509726a37 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -316,38 +316,38 @@ module ActionView
private
- def render_collection
- instrument(:collection, count: @collection.size) do |payload|
- return nil if @collection.blank?
+ def render_collection
+ instrument(:collection, count: @collection.size) do |payload|
+ return nil if @collection.blank?
- if @options.key?(:spacer_template)
- spacer = find_template(@options[:spacer_template], @locals.keys).render(@view, @locals)
- end
+ if @options.key?(:spacer_template)
+ spacer = find_template(@options[:spacer_template], @locals.keys).render(@view, @locals)
+ end
- cache_collection_render(payload) do
- @template ? collection_with_template : collection_without_template
- end.join(spacer).html_safe
+ cache_collection_render(payload) do
+ @template ? collection_with_template : collection_without_template
+ end.join(spacer).html_safe
+ end
end
- end
- def render_partial
- view, locals, block = @view, @locals, @block
- object, as = @object, @variable
+ def render_partial
+ view, locals, block = @view, @locals, @block
+ object, as = @object, @variable
- if !block && (layout = @options[:layout])
- layout = find_template(layout.to_s, @template_keys)
- end
+ if !block && (layout = @options[:layout])
+ layout = find_template(layout.to_s, @template_keys)
+ end
- object = locals[as] if object.nil? # Respect object when object is false
- locals[as] = object if @has_object
+ object = locals[as] if object.nil? # Respect object when object is false
+ locals[as] = object if @has_object
- content = @template.render(view, locals) do |*name|
- view._layout_for(*name, &block)
- end
+ content = @template.render(view, locals) do |*name|
+ view._layout_for(*name, &block)
+ end
- content = layout.render(view, locals){ content } if layout
- content
- end
+ content = layout.render(view, locals){ content } if layout
+ content
+ end
# Sets up instance variables needed for rendering a partial. This method
# finds the options and details and extracts them. The method also contains
@@ -356,114 +356,114 @@ module ActionView
# If +options[:partial]+ is a string, then the +@path+ instance variable is
# set to that string. Otherwise, the +options[:partial]+ object must
# respond to +to_partial_path+ in order to setup the path.
- def setup(context, options, block)
- @view = context
- @options = options
- @block = block
+ def setup(context, options, block)
+ @view = context
+ @options = options
+ @block = block
- @locals = options[:locals] || {}
- @details = extract_details(options)
+ @locals = options[:locals] || {}
+ @details = extract_details(options)
- prepend_formats(options[:formats])
+ prepend_formats(options[:formats])
- partial = options[:partial]
+ partial = options[:partial]
- if String === partial
- @has_object = options.key?(:object)
- @object = options[:object]
- @collection = collection_from_options
- @path = partial
- else
- @has_object = true
- @object = partial
- @collection = collection_from_object || collection_from_options
+ if String === partial
+ @has_object = options.key?(:object)
+ @object = options[:object]
+ @collection = collection_from_options
+ @path = partial
+ else
+ @has_object = true
+ @object = partial
+ @collection = collection_from_object || collection_from_options
+
+ if @collection
+ paths = @collection_data = @collection.map { |o| partial_path(o) }
+ @path = paths.uniq.one? ? paths.first : nil
+ else
+ @path = partial_path
+ end
+ end
- if @collection
- paths = @collection_data = @collection.map { |o| partial_path(o) }
- @path = paths.uniq.one? ? paths.first : nil
+ if as = options[:as]
+ raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)
+ as = as.to_sym
+ end
+
+ if @path
+ @variable, @variable_counter, @variable_iteration = retrieve_variable(@path, as)
+ @template_keys = retrieve_template_keys
else
- @path = partial_path
+ paths.map! { |path| retrieve_variable(path, as).unshift(path) }
end
+
+ self
end
- if as = options[:as]
- raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)
- as = as.to_sym
+ def collection_from_options
+ if @options.key?(:collection)
+ collection = @options[:collection]
+ collection ? collection.to_a : []
+ end
end
- if @path
- @variable, @variable_counter, @variable_iteration = retrieve_variable(@path, as)
- @template_keys = retrieve_template_keys
- else
- paths.map! { |path| retrieve_variable(path, as).unshift(path) }
+ def collection_from_object
+ @object.to_ary if @object.respond_to?(:to_ary)
end
- self
- end
+ def find_partial
+ find_template(@path, @template_keys) if @path
+ end
- def collection_from_options
- if @options.key?(:collection)
- collection = @options[:collection]
- collection ? collection.to_a : []
+ def find_template(path, locals)
+ prefixes = path.include?(?/) ? [] : @lookup_context.prefixes
+ @lookup_context.find_template(path, prefixes, true, locals, @details)
end
- end
- def collection_from_object
- @object.to_ary if @object.respond_to?(:to_ary)
- end
+ def collection_with_template
+ view, locals, template = @view, @locals, @template
+ as, counter, iteration = @variable, @variable_counter, @variable_iteration
- def find_partial
- find_template(@path, @template_keys) if @path
- end
+ if layout = @options[:layout]
+ layout = find_template(layout, @template_keys)
+ end
- def find_template(path, locals)
- prefixes = path.include?(?/) ? [] : @lookup_context.prefixes
- @lookup_context.find_template(path, prefixes, true, locals, @details)
- end
+ partial_iteration = PartialIteration.new(@collection.size)
+ locals[iteration] = partial_iteration
- def collection_with_template
- view, locals, template = @view, @locals, @template
- as, counter, iteration = @variable, @variable_counter, @variable_iteration
+ @collection.map do |object|
+ locals[as] = object
+ locals[counter] = partial_iteration.index
- if layout = @options[:layout]
- layout = find_template(layout, @template_keys)
+ content = template.render(view, locals)
+ content = layout.render(view, locals) { content } if layout
+ partial_iteration.iterate!
+ content
+ end
end
- partial_iteration = PartialIteration.new(@collection.size)
- locals[iteration] = partial_iteration
-
- @collection.map do |object|
- locals[as] = object
- locals[counter] = partial_iteration.index
-
- content = template.render(view, locals)
- content = layout.render(view, locals) { content } if layout
- partial_iteration.iterate!
- content
- end
- end
+ def collection_without_template
+ view, locals, collection_data = @view, @locals, @collection_data
+ cache = {}
+ keys = @locals.keys
- def collection_without_template
- view, locals, collection_data = @view, @locals, @collection_data
- cache = {}
- keys = @locals.keys
+ partial_iteration = PartialIteration.new(@collection.size)
- partial_iteration = PartialIteration.new(@collection.size)
+ @collection.map do |object|
+ index = partial_iteration.index
+ path, as, counter, iteration = collection_data[index]
- @collection.map do |object|
- index = partial_iteration.index
- path, as, counter, iteration = collection_data[index]
+ locals[as] = object
+ locals[counter] = index
+ locals[iteration] = partial_iteration
- locals[as] = object
- locals[counter] = index
- locals[iteration] = partial_iteration
-
- template = (cache[path] ||= find_template(path, keys + [as, counter]))
- content = template.render(view, locals)
- partial_iteration.iterate!
- content
+ template = (cache[path] ||= find_template(path, keys + [as, counter]))
+ content = template.render(view, locals)
+ partial_iteration.iterate!
+ content
+ end
end
- end
# Obtains the path to where the object's partial is located. If the object
# responds to +to_partial_path+, then +to_partial_path+ will be called and
@@ -472,79 +472,79 @@ module ActionView
#
# If +prefix_partial_path_with_controller_namespace+ is true, then this
# method will prefix the partial paths with a namespace.
- def partial_path(object = @object)
- object = object.to_model if object.respond_to?(:to_model)
+ def partial_path(object = @object)
+ object = object.to_model if object.respond_to?(:to_model)
- path = if object.respond_to?(:to_partial_path)
- object.to_partial_path
- else
- raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.")
+ path = if object.respond_to?(:to_partial_path)
+ object.to_partial_path
+ else
+ raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.")
+ end
+
+ if @view.prefix_partial_path_with_controller_namespace
+ prefixed_partial_names[path] ||= merge_prefix_into_object_path(@context_prefix, path.dup)
+ else
+ path
+ end
end
- if @view.prefix_partial_path_with_controller_namespace
- prefixed_partial_names[path] ||= merge_prefix_into_object_path(@context_prefix, path.dup)
- else
- path
+ def prefixed_partial_names
+ @prefixed_partial_names ||= PREFIXED_PARTIAL_NAMES[@context_prefix]
end
- end
- def prefixed_partial_names
- @prefixed_partial_names ||= PREFIXED_PARTIAL_NAMES[@context_prefix]
- end
+ def merge_prefix_into_object_path(prefix, object_path)
+ if prefix.include?(?/) && object_path.include?(?/)
+ prefixes = []
+ prefix_array = File.dirname(prefix).split("/")
+ object_path_array = object_path.split("/")[0..-3] # skip model dir & partial
- def merge_prefix_into_object_path(prefix, object_path)
- if prefix.include?(?/) && object_path.include?(?/)
- prefixes = []
- prefix_array = File.dirname(prefix).split("/")
- object_path_array = object_path.split("/")[0..-3] # skip model dir & partial
+ prefix_array.each_with_index do |dir, index|
+ break if dir == object_path_array[index]
+ prefixes << dir
+ end
- prefix_array.each_with_index do |dir, index|
- break if dir == object_path_array[index]
- prefixes << dir
+ (prefixes << object_path).join("/")
+ else
+ object_path
end
-
- (prefixes << object_path).join("/")
- else
- object_path
end
- end
- def retrieve_template_keys
- keys = @locals.keys
- keys << @variable if @has_object || @collection
- if @collection
- keys << @variable_counter
- keys << @variable_iteration
+ def retrieve_template_keys
+ keys = @locals.keys
+ keys << @variable if @has_object || @collection
+ if @collection
+ keys << @variable_counter
+ keys << @variable_iteration
+ end
+ keys
end
- keys
- end
- def retrieve_variable(path, as)
- variable = as || begin
- base = path[-1] == "/".freeze ? "".freeze : File.basename(path)
- raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
- $1.to_sym
- end
- if @collection
- variable_counter = :"#{variable}_counter"
- variable_iteration = :"#{variable}_iteration"
+ def retrieve_variable(path, as)
+ variable = as || begin
+ base = path[-1] == "/".freeze ? "".freeze : File.basename(path)
+ raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
+ $1.to_sym
+ end
+ if @collection
+ variable_counter = :"#{variable}_counter"
+ variable_iteration = :"#{variable}_iteration"
+ end
+ [variable, variable_counter, variable_iteration]
end
- [variable, variable_counter, variable_iteration]
- end
- IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " +
- "make sure your partial name starts with underscore."
+ IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " +
+ "make sure your partial name starts with underscore."
- OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " +
- "make sure it starts with lowercase letter, " +
- "and is followed by any combination of letters, numbers and underscores."
+ OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " +
+ "make sure it starts with lowercase letter, " +
+ "and is followed by any combination of letters, numbers and underscores."
- def raise_invalid_identifier(path)
- raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % (path))
- end
+ def raise_invalid_identifier(path)
+ raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % (path))
+ end
- def raise_invalid_option_as(as)
- raise ArgumentError.new(OPTION_AS_ERROR_MESSAGE % (as))
- end
+ def raise_invalid_option_as(as)
+ raise ArgumentError.new(OPTION_AS_ERROR_MESSAGE % (as))
+ end
end
end
diff --git a/actionview/lib/action_view/renderer/streaming_template_renderer.rb b/actionview/lib/action_view/renderer/streaming_template_renderer.rb
index f49cf589f8..0323ebef6a 100644
--- a/actionview/lib/action_view/renderer/streaming_template_renderer.rb
+++ b/actionview/lib/action_view/renderer/streaming_template_renderer.rb
@@ -29,15 +29,15 @@ module ActionView
# This is the same logging logic as in ShowExceptions middleware.
# TODO Once "exceptron" is in, refactor this piece to simply re-use exceptron.
- def log_error(exception) #:nodoc:
- logger = ActionView::Base.logger
- return unless logger
-
- message = "\n#{exception.class} (#{exception.message}):\n"
- message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
- message << " " << exception.backtrace.join("\n ")
- logger.fatal("#{message}\n\n")
- end
+ def log_error(exception) #:nodoc:
+ logger = ActionView::Base.logger
+ return unless logger
+
+ message = "\n#{exception.class} (#{exception.message}):\n"
+ message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
+ message << " " << exception.backtrace.join("\n ")
+ logger.fatal("#{message}\n\n")
+ end
end
# For streaming, instead of rendering a given a template, we return a Body
@@ -56,48 +56,48 @@ module ActionView
private
- def delayed_render(buffer, template, layout, view, locals)
- # Wrap the given buffer in the StreamingBuffer and pass it to the
- # underlying template handler. Now, every time something is concatenated
- # to the buffer, it is not appended to an array, but streamed straight
- # to the client.
- output = ActionView::StreamingBuffer.new(buffer)
- yielder = lambda { |*name| view._layout_for(*name) }
-
- instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
- fiber = Fiber.new do
- if layout
- layout.render(view, locals, output, &yielder)
- else
- # If you don't have a layout, just render the thing
- # and concatenate the final result. This is the same
- # as a layout with just <%= yield %>
- output.safe_concat view._layout_for
+ def delayed_render(buffer, template, layout, view, locals)
+ # Wrap the given buffer in the StreamingBuffer and pass it to the
+ # underlying template handler. Now, every time something is concatenated
+ # to the buffer, it is not appended to an array, but streamed straight
+ # to the client.
+ output = ActionView::StreamingBuffer.new(buffer)
+ yielder = lambda { |*name| view._layout_for(*name) }
+
+ instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
+ fiber = Fiber.new do
+ if layout
+ layout.render(view, locals, output, &yielder)
+ else
+ # If you don't have a layout, just render the thing
+ # and concatenate the final result. This is the same
+ # as a layout with just <%= yield %>
+ output.safe_concat view._layout_for
+ end
end
- end
- # Set the view flow to support streaming. It will be aware
- # when to stop rendering the layout because it needs to search
- # something in the template and vice-versa.
- view.view_flow = StreamingFlow.new(view, fiber)
+ # Set the view flow to support streaming. It will be aware
+ # when to stop rendering the layout because it needs to search
+ # something in the template and vice-versa.
+ view.view_flow = StreamingFlow.new(view, fiber)
- # Yo! Start the fiber!
- fiber.resume
+ # Yo! Start the fiber!
+ fiber.resume
- # If the fiber is still alive, it means we need something
- # from the template, so start rendering it. If not, it means
- # the layout exited without requiring anything from the template.
- if fiber.alive?
- content = template.render(view, locals, &yielder)
+ # If the fiber is still alive, it means we need something
+ # from the template, so start rendering it. If not, it means
+ # the layout exited without requiring anything from the template.
+ if fiber.alive?
+ content = template.render(view, locals, &yielder)
- # Once rendering the template is done, sets its content in the :layout key.
- view.view_flow.set(:layout, content)
+ # Once rendering the template is done, sets its content in the :layout key.
+ view.view_flow.set(:layout, content)
- # In case the layout continues yielding, we need to resume
- # the fiber until all yields are handled.
- fiber.resume while fiber.alive?
+ # In case the layout continues yielding, we need to resume
+ # the fiber until all yields are handled.
+ fiber.resume while fiber.alive?
+ end
end
end
- end
end
end
diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb
index 333413c4a1..0151653b73 100644
--- a/actionview/lib/action_view/renderer/template_renderer.rb
+++ b/actionview/lib/action_view/renderer/template_renderer.rb
@@ -17,86 +17,86 @@ module ActionView
private
# Determine the template to be rendered using the given options.
- def determine_template(options)
- keys = options.has_key?(:locals) ? options[:locals].keys : []
+ def determine_template(options)
+ keys = options.has_key?(:locals) ? options[:locals].keys : []
- if options.key?(:body)
- Template::Text.new(options[:body])
- elsif options.key?(:text)
- Template::Text.new(options[:text], formats.first)
- elsif options.key?(:plain)
- Template::Text.new(options[:plain])
- elsif options.key?(:html)
- Template::HTML.new(options[:html], formats.first)
- elsif options.key?(:file)
- with_fallbacks { find_file(options[:file], nil, false, keys, @details) }
- elsif options.key?(:inline)
- handler = Template.handler_for_extension(options[:type] || "erb")
- Template.new(options[:inline], "inline template", handler, locals: keys)
- elsif options.key?(:template)
- if options[:template].respond_to?(:render)
- options[:template]
+ if options.key?(:body)
+ Template::Text.new(options[:body])
+ elsif options.key?(:text)
+ Template::Text.new(options[:text], formats.first)
+ elsif options.key?(:plain)
+ Template::Text.new(options[:plain])
+ elsif options.key?(:html)
+ Template::HTML.new(options[:html], formats.first)
+ elsif options.key?(:file)
+ with_fallbacks { find_file(options[:file], nil, false, keys, @details) }
+ elsif options.key?(:inline)
+ handler = Template.handler_for_extension(options[:type] || "erb")
+ Template.new(options[:inline], "inline template", handler, locals: keys)
+ elsif options.key?(:template)
+ if options[:template].respond_to?(:render)
+ options[:template]
+ else
+ find_template(options[:template], options[:prefixes], false, keys, @details)
+ end
else
- find_template(options[:template], options[:prefixes], false, keys, @details)
+ raise ArgumentError, "You invoked render but did not give any of :partial, :template, :inline, :file, :plain, :html, :text or :body option."
end
- else
- raise ArgumentError, "You invoked render but did not give any of :partial, :template, :inline, :file, :plain, :html, :text or :body option."
end
- end
# Renders the given template. A string representing the layout can be
# supplied as well.
- def render_template(template, layout_name = nil, locals = nil) #:nodoc:
- view, locals = @view, locals || {}
+ def render_template(template, layout_name = nil, locals = nil) #:nodoc:
+ view, locals = @view, locals || {}
- render_with_layout(layout_name, locals) do |layout|
- instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
- template.render(view, locals) { |*name| view._layout_for(*name) }
+ render_with_layout(layout_name, locals) do |layout|
+ instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
+ template.render(view, locals) { |*name| view._layout_for(*name) }
+ end
end
end
- end
- def render_with_layout(path, locals) #:nodoc:
- layout = path && find_layout(path, locals.keys, [formats.first])
- content = yield(layout)
+ def render_with_layout(path, locals) #:nodoc:
+ layout = path && find_layout(path, locals.keys, [formats.first])
+ content = yield(layout)
- if layout
- view = @view
- view.view_flow.set(:layout, content)
- layout.render(view, locals){ |*name| view._layout_for(*name) }
- else
- content
+ if layout
+ view = @view
+ view.view_flow.set(:layout, content)
+ layout.render(view, locals){ |*name| view._layout_for(*name) }
+ else
+ content
+ end
end
- end
# This is the method which actually finds the layout using details in the lookup
# context object. If no layout is found, it checks if at least a layout with
# the given name exists across all details before raising the error.
- def find_layout(layout, keys, formats)
- resolve_layout(layout, keys, formats)
- end
+ def find_layout(layout, keys, formats)
+ resolve_layout(layout, keys, formats)
+ end
- def resolve_layout(layout, keys, formats)
- details = @details.dup
- details[:formats] = formats
+ def resolve_layout(layout, keys, formats)
+ details = @details.dup
+ details[:formats] = formats
- case layout
- when String
- begin
- if layout.start_with?("/")
- with_fallbacks { find_template(layout, nil, false, [], details) }
- else
- find_template(layout, nil, false, [], details)
+ case layout
+ when String
+ begin
+ if layout.start_with?("/")
+ with_fallbacks { find_template(layout, nil, false, [], details) }
+ else
+ find_template(layout, nil, false, [], details)
+ end
+ rescue ActionView::MissingTemplate
+ all_details = @details.merge(formats: @lookup_context.default_formats)
+ raise unless template_exists?(layout, nil, false, [], all_details)
end
- rescue ActionView::MissingTemplate
- all_details = @details.merge(formats: @lookup_context.default_formats)
- raise unless template_exists?(layout, nil, false, [], all_details)
+ when Proc
+ resolve_layout(layout.call(formats), keys, formats)
+ else
+ layout
end
- when Proc
- resolve_layout(layout.call(formats), keys, formats)
- else
- layout
end
- end
end
end