class ActionView::RenderParser
:nodoc:
def directory
def directory File.dirname(@name) end
def initialize(name, code)
def initialize(name, code) @name = name @code = code @parser = RipperASTParser end
def layout_to_virtual_path(layout_path)
def layout_to_virtual_path(layout_path) "layouts/#{layout_path}" end
def normalize_args(string, options_hash)
or
render(template: "foo", ...)
into either
render("foo", ...)
Convert
def normalize_args(string, options_hash) if options_hash { partial: string, locals: options_hash } else { partial: string } end end
def parse_hash(node)
def parse_hash(node) node.hash? && node.to_hash end
def parse_hash_to_symbols(node)
def parse_hash_to_symbols(node) hash = parse_hash(node) return unless hash hash.transform_keys do |key_node| key = parse_sym(key_node) return unless key key end end
def parse_render(node)
def parse_render(node) node = node.argument_nodes if (node.length == 1 || node.length == 2) && !node[0].hash? if node.length == 1 options = normalize_args(node[0], nil) elsif node.length == 2 options = normalize_args(node[0], node[1]) end return nil unless options parse_render_from_options(options) elsif node.length == 1 && node[0].hash? options = parse_hash_to_symbols(node[0]) return nil unless options parse_render_from_options(options) else nil end end
def parse_render_from_options(options_hash)
def parse_render_from_options(options_hash) renders = [] keys = options_hash.keys if (keys & RENDER_TYPE_KEYS).size < 1 # Must have at least one of render keys return nil end if (keys - ALL_KNOWN_KEYS).any? # de-opt in case of unknown option return nil end render_type = (keys & RENDER_TYPE_KEYS)[0] node = options_hash[render_type] if node.string? template = resolve_path_directory(node.to_string) else if node.variable_reference? dependency = node.variable_name.sub(/\A(?:\$|@{1,2})/, "") elsif node.vcall? dependency = node.variable_name elsif node.call? dependency = node.call_method_name else return end object_template = true template = "#{dependency.pluralize}/#{dependency.singularize}" end return unless template if spacer_template = render_template_with_spacer?(options_hash) virtual_path = partial_to_virtual_path(:partial, spacer_template) renders << virtual_path end if options_hash.key?(:object) || options_hash.key?(:collection) || object_template return nil if options_hash.key?(:object) && options_hash.key?(:collection) return nil unless options_hash.key?(:partial) end virtual_path = partial_to_virtual_path(render_type, template) renders << virtual_path # Support for rendering multiple templates (i.e. a partial with a layout) if layout_template = render_template_with_layout?(render_type, options_hash) virtual_path = partial_to_virtual_path(:layout, layout_template) renders << virtual_path end renders end
def parse_str(node)
def parse_str(node) node.string? && node.to_string end
def parse_sym(node)
def parse_sym(node) node.symbol? && node.to_symbol end
def partial_to_virtual_path(render_type, partial_path)
def partial_to_virtual_path(render_type, partial_path) if render_type == :partial || render_type == :layout partial_path.gsub(%r{(/|^)([^/]*)\z}, '\1_\2') else partial_path end end
def render_calls
def render_calls render_nodes = @parser.parse_render_nodes(@code) render_nodes.map do |method, nodes| nodes.map { |n| send(:parse_render, n) } end.flatten.compact end
def render_template_with_layout?(render_type, options_hash)
def render_template_with_layout?(render_type, options_hash) if render_type != :layout && options_hash.key?(:layout) parse_str(options_hash[:layout]) end end
def render_template_with_spacer?(options_hash)
def render_template_with_spacer?(options_hash) if options_hash.key?(:spacer_template) parse_str(options_hash[:spacer_template]) end end
def resolve_path_directory(path)
def resolve_path_directory(path) if path.include?("/") path else "#{directory}/#{path}" end end