From 1997634dfc996689c40a15641d4b6c42b23e199f Mon Sep 17 00:00:00 2001 From: ccocchi Date: Thu, 23 Feb 2012 12:04:55 +0100 Subject: [PATCH] Add child support and bacic node --- lib/rabl-fast-json/compiler.rb | 39 ++++++++++++++++++++++++++++++---- test/compiler_test.rb | 28 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/lib/rabl-fast-json/compiler.rb b/lib/rabl-fast-json/compiler.rb index 0fddc0f..ba4c9a6 100644 --- a/lib/rabl-fast-json/compiler.rb +++ b/lib/rabl-fast-json/compiler.rb @@ -3,9 +3,9 @@ require 'singleton' module RablFastJson class Compiler - def initialize(context) + def initialize(context, assigns = nil) @context = context - _get_assigns_from_context + _get_assigns_from_context(assigns) _get_virtual_path_from_context end @@ -15,6 +15,12 @@ module RablFastJson @template end + def compile_block(&block) + @template = {} + instance_eval(&block) + @template + end + def attribute(*args) if args.first.is_a?(Hash) args.first.each_pair { |k, v| @template[v] = k } @@ -24,6 +30,19 @@ module RablFastJson end 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 = {}) @data = data.to_a if data end @@ -34,8 +53,20 @@ module RablFastJson protected - def _get_assigns_from_context - @context.instance_variable_get(:@_assigns).each_pair { |k, v| + def extract_name_and_data(name_or_data) + 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?('_') } end diff --git a/test/compiler_test.rb b/test/compiler_test.rb index 0e5c112..1f41616 100644 --- a/test/compiler_test.rb +++ b/test/compiler_test.rb @@ -19,6 +19,7 @@ class CompilerTest < ActiveSupport::TestCase end class User + attr_accessor :name end setup do @@ -36,6 +37,12 @@ class CompilerTest < ActiveSupport::TestCase assert_equal '/users', @compiler.instance_variable_get(:@virtual_path) 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 assert_instance_of RablFastJson::CompiledTemplate, @compiler.compile_source("") end @@ -59,4 +66,25 @@ class CompilerTest < ActiveSupport::TestCase t = @compiler.compile_source(%{ attributes :foo => :bar, :id => :uid }) assert_equal({ :bar => :foo, :uid => :id }, t.source) 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 \ No newline at end of file