1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
module RablRails
module Renderers
module Hash
include ::RablRails::Helpers
extend self
#
# Render a template.
# Uses the compiled template source to get a hash with the actual
# data and then format the result according to the `format_result`
# method defined by the renderer.
#
def render(template, context, locals = nil)
visitor = Visitors::ToHash.new(context)
collection_or_resource = if template.data
if context.respond_to?(template.data)
context.send(template.data)
else
visitor.instance_variable_get(template.data)
end
end
collection_or_resource ||= locals[:resource] if locals
render_with_cache(template.cache_key, collection_or_resource) do
output_hash = if collection?(collection_or_resource)
render_collection(collection_or_resource, template.nodes, visitor)
else
render_resource(collection_or_resource, template.nodes, visitor)
end
format_output(output_hash, root_name: template.root_name, params: context.params)
end
end
protected
#
# Format a hash into the desired output.
# Renderer subclasses must implement this method
#
def format_output(hash, options = {})
hash = { options[:root_name] => hash } if options[:root_name]
hash
end
private
#
# Render a single resource as a hash, according to the compiled
# template source passed.
#
def render_resource(resource, nodes, visitor)
visitor.reset_for resource
visitor.visit nodes
visitor.result
end
#
# Call the render_resource mtehod on each object of the collection
# and return an array of the returned values.
#
def render_collection(collection, nodes, visitor)
collection.map { |o| render_resource(o, nodes, visitor) }
end
def resolve_cache_key(key, data)
return data.cache_key unless key
key.is_a?(Proc) ? instance_exec(data, &key) : key
end
private
def render_with_cache(key, collection_or_resource)
if !key.is_a?(FalseClass) && ActionController::Base.perform_caching
Rails.cache.fetch(resolve_cache_key(key, collection_or_resource)) do
yield
end
else
yield
end
end
end
end
end
|