Add child support and bacic node

This commit is contained in:
ccocchi 2012-02-23 12:04:55 +01:00
parent 2460ef14e3
commit 1997634dfc
2 changed files with 63 additions and 4 deletions

View File

@ -3,9 +3,9 @@ require 'singleton'
module RablFastJson module RablFastJson
class Compiler class Compiler
def initialize(context) def initialize(context, assigns = nil)
@context = context @context = context
_get_assigns_from_context _get_assigns_from_context(assigns)
_get_virtual_path_from_context _get_virtual_path_from_context
end end
@ -15,6 +15,12 @@ module RablFastJson
@template @template
end end
def compile_block(&block)
@template = {}
instance_eval(&block)
@template
end
def attribute(*args) def attribute(*args)
if args.first.is_a?(Hash) if args.first.is_a?(Hash)
args.first.each_pair { |k, v| @template[v] = k } args.first.each_pair { |k, v| @template[v] = k }
@ -24,6 +30,19 @@ module RablFastJson
end end
alias_method :attributes, :attribute alias_method :attributes, :attribute
def child(name_or_data, options = {}, &block)
return unless block_given?
data, name = extract_name_and_data(name_or_data)
sub_compiler = Compiler.new(@context, @assigns)
sub_template = sub_compiler.compile_block(&block)
@template[name] = sub_template.merge!(:_data => data)
end
def node(name, options = {}, &block)
@template[name] = block
end
alias_method :code, :node
def collection(data, options = {}) def collection(data, options = {})
@data = data.to_a if data @data = data.to_a if data
end end
@ -34,8 +53,20 @@ module RablFastJson
protected protected
def _get_assigns_from_context def extract_name_and_data(name_or_data)
@context.instance_variable_get(:@_assigns).each_pair { |k, v| case name_or_data
when Symbol
[name_or_data, name_or_data]
when Hash
name_or_data.first
else
raise "#{name_or_data} is not a valid name for a child association"
end
end
def _get_assigns_from_context(assigns)
source = assigns || @context.instance_variable_get(:@_assigns)
source.each_pair { |k, v|
instance_variable_set("@#{k}", v) unless k.start_with?('_') instance_variable_set("@#{k}", v) unless k.start_with?('_')
} }
end end

View File

@ -19,6 +19,7 @@ class CompilerTest < ActiveSupport::TestCase
end end
class User class User
attr_accessor :name
end end
setup do setup do
@ -36,6 +37,12 @@ class CompilerTest < ActiveSupport::TestCase
assert_equal '/users', @compiler.instance_variable_get(:@virtual_path) assert_equal '/users', @compiler.instance_variable_get(:@virtual_path)
end end
test "assigns are not imported if already passed to the compiler" do
compiler = RablFastJson::Compiler.new(@context, { 'other' => 'foo' })
assert_nil compiler.instance_variable_get(:@user)
assert_equal 'foo', compiler.instance_variable_get(:@other)
end
test "compiler return a compiled template" do test "compiler return a compiled template" do
assert_instance_of RablFastJson::CompiledTemplate, @compiler.compile_source("") assert_instance_of RablFastJson::CompiledTemplate, @compiler.compile_source("")
end end
@ -59,4 +66,25 @@ class CompilerTest < ActiveSupport::TestCase
t = @compiler.compile_source(%{ attributes :foo => :bar, :id => :uid }) t = @compiler.compile_source(%{ attributes :foo => :bar, :id => :uid })
assert_equal({ :bar => :foo, :uid => :id }, t.source) assert_equal({ :bar => :foo, :uid => :id }, t.source)
end end
test "child with association use association name as data" do
t = @compiler.compile_source(%{ child :address do attributes :foo end})
assert_equal({ :address => { :_data => :address, :foo => :foo } }, t.source)
end
test "child with association can be aliased" do
t = @compiler.compile_source(%{ child :address => :bar do attributes :foo end})
assert_equal({ :bar => { :_data => :address, :foo => :foo } }, t.source)
end
test "child with arbitrary source store the data with the template" do
t = @compiler.compile_source(%{ child @user => :author do attribute :name end })
assert_equal({ :author => { :_data => @user, :name => :name } }, t.source)
end
test "node are compiled without evaluating the block" do
t = @compiler.compile_source(%{ node(:foo) { bar } })
assert_not_nil t.source[:foo]
assert_instance_of Proc, t.source[:foo]
end
end end