lib/volt/server/html_parser/component_view_scope.rb
module Volt
class ComponentViewScope < ViewScope
# The path passed in is the path used to lookup view's. The path from the tag is passed in
# as tag_name
def initialize(handler, path, tag_name, attributes, unary)
super(handler, path)
@binding_in_path = path
component_name = tag_name[1..-1].tr('-', '_').tr(':', '/')
data_hash = []
attributes.each_pair do |name, value|
name = name.tr('-', '_')
if name[0..1] == 'e_'
# Event binding
value = ViewScope.methodize_string(value.strip)
data_hash << "#{name.inspect} => Proc.new {|event| #{value} }"
else
parts, binding_count = binding_parts_and_count(value)
# if this attribute has bindings
if binding_count > 0
if binding_count > 1
# Multiple bindings
elsif parts.size == 1 && binding_count == 1
# A single binding
getter = value[2...-2].strip
data_hash << "#{name.inspect} => Proc.new { #{getter} }"
setter = getter_to_setter(getter)
data_hash << "#{(name + '=').inspect} => Proc.new { |val| #{setter} }"
# Add an _parent fetcher. Useful for things like volt-fields to get the parent model.
parent = parent_fetcher(getter)
# TODO: This adds some overhead, perhaps there is a way to compute this dynamically on the
# front-end.
data_hash << "#{(name + '_parent').inspect} => Proc.new { #{parent} }"
# Add a _last_method property. This is useful
data_hash << "#{(name + '_last_method').inspect} => #{last_method_name(getter).inspect}"
end
else
# String
data_hash << "#{name.inspect} => #{value.inspect}"
end
end
end
@arguments = "#{component_name.inspect}, { #{data_hash.join(',')} }"
end
def close_scope
binding_number = @handler.scope[-2].binding_number
@handler.scope[-2].binding_number += 1
@path += "/__template/#{binding_number}"
super
@handler.html << "<!-- $#{binding_number} --><!-- $/#{binding_number} -->"
@handler.scope.last.save_binding(binding_number, "lambda { |__p, __t, __c, __id| Volt::ComponentBinding.new(__p, __t, __c, __id, #{@binding_in_path.inspect}, Proc.new { [#{@arguments}] }, #{@path.inspect}) }")
end
end
end