class ActionviewPrecompiler::RenderParser

Constants

ALL_KNOWN_KEYS
IGNORED_KEYS
RENDER_TYPE_KEYS

Public Class Methods

new(code) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 15
def initialize(code)
  @code = code
  @code = parse(code) if code.is_a?(String)
end

Public Instance Methods

render_calls() click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 20
def render_calls
  render_nodes = extract_render_nodes(@code)
  render_nodes.map do |node|
    parse_render(node)
  end.compact
end

Private Instance Methods

debug(message) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 126
def debug(message)
  warn message
end
extract_render_nodes(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 130
def extract_render_nodes(node)
  return [] unless node?(node)
  renders = node.children.flat_map { |c| extract_render_nodes(c) }
  if render_call?(node)
    renders << node
  end
  renders
end
parse_hash(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 48
def parse_hash(node)
  node.hash? && node.to_hash
end
parse_hash_to_symbols(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 52
def parse_hash_to_symbols(node)
  hash = parse_hash(node)
  return unless hash
  hash.transform_keys do |node|
    key = parse_sym(node)
    return unless key
    key
  end
end
parse_render(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 29
def parse_render(node)
  node = node.argument_nodes
  if (node.length == 1 || node.length == 2) && node[0].string?
    # FIXME: from template vs controller
    options = {}
    options[:partial] = node[0]
    if node.length == 2
      return unless node[1].hash?
      options[:locals] = node[1]
    end
    return parse_render_from_options(options)
  elsif node.length == 1 && node[0].hash?
    options = parse_hash_to_symbols(node[0])
    return parse_render_from_options(options)
  else
    nil
  end
end
parse_render_from_options(options_hash) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 66
def parse_render_from_options(options_hash)
  keys = options_hash.keys

  unless (keys & RENDER_TYPE_KEYS).one?
    # Must have one of partial:, template:, or layout:
    return nil
  end

  unless (keys - ALL_KNOWN_KEYS).empty?
    # de-opt in case of unknown option
    return nil
  end

  render_type = (keys & RENDER_TYPE_KEYS)[0]
  template = parse_str(options_hash[render_type])
  return unless template

  if options_hash.key?(:locals)
    locals = options_hash[:locals]
    parsed_locals = parse_hash(locals)
    return nil unless parsed_locals
    locals_keys = parsed_locals.keys.map do |local|
      return nil unless local.symbol?
      local.to_symbol
    end
  else
    locals = nil
    locals_keys = []
  end

  if options_hash.key?(:object) || options_hash.key?(:collection)
    return nil if options_hash.key?(:object) && options_hash.key?(:collection)
    return nil unless options_hash.key?(:partial)

    as = if options_hash.key?(:as)
           parse_str(options_hash[:as]) || parse_sym(options_hash[:as])
         elsif File.basename(template) =~ /\A_?(.*?)(?:\.\w+)*\z/
           $1
         end

    return nil unless as

    locals_keys << as.to_sym
    if options_hash.key?(:collection)
      locals_keys << :"#{as}_counter"
      locals_keys << :"#{as}_iteration"
    end
  end

  RenderCall.new(render_type, template, locals, locals_keys)
end
parse_str(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 118
def parse_str(node)
  node.string? && node.to_string
end
parse_sym(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 122
def parse_sym(node)
  node.symbol? && node.to_symbol
end
render_call?(node) click to toggle source
# File lib/actionview_precompiler/render_parser.rb, line 139
def render_call?(node)
  fcall?(node, :render)
end