Fix deep nesting case
This commit is contained in:
parent
844b2703e2
commit
1a033a60c2
@ -1,7 +1,7 @@
|
|||||||
module RablFastJson
|
module RablFastJson
|
||||||
class Compiler
|
class Compiler
|
||||||
|
|
||||||
def initialize(context = nil, assigns = nil)
|
def initialize(context = nil)
|
||||||
@context = context
|
@context = context
|
||||||
@glue_count = 0
|
@glue_count = 0
|
||||||
end
|
end
|
||||||
@ -50,7 +50,7 @@ module RablFastJson
|
|||||||
end
|
end
|
||||||
|
|
||||||
def extends(path)
|
def extends(path)
|
||||||
t = Library.instance.get(path)
|
t = Library.instance.get(path, @context)
|
||||||
@template.merge!(t.source)
|
@template.merge!(t.source)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ module RablFastJson
|
|||||||
end
|
end
|
||||||
|
|
||||||
def _compile_sub_template(name, data, &block)
|
def _compile_sub_template(name, data, &block)
|
||||||
compiler = Compiler.new(@context, @assigns)
|
compiler = Compiler.new(@context)
|
||||||
template = compiler.compile_block(&block)
|
template = compiler.compile_block(&block)
|
||||||
@template[name] = template.merge!(:_data => data)
|
@template[name] = template.merge!(:_data => data)
|
||||||
end
|
end
|
||||||
|
@ -11,33 +11,22 @@ module RablFastJson
|
|||||||
def get_rendered_template(source, context)
|
def get_rendered_template(source, context)
|
||||||
path = context.instance_variable_get(:@virtual_path)
|
path = context.instance_variable_get(:@virtual_path)
|
||||||
@view_renderer = context.instance_variable_get(:@view_renderer)
|
@view_renderer = context.instance_variable_get(:@view_renderer)
|
||||||
start = Time.now
|
|
||||||
compiled_template = get_compiled_template(path, source, context)
|
compiled_template = get_compiled_template(path, source, context)
|
||||||
compiled_time = Time.now
|
|
||||||
compiled_template.context = context
|
compiled_template.context = context
|
||||||
r = compiled_template.render
|
|
||||||
render_time = Time.now
|
|
||||||
res = ActiveSupport::JSON.encode(r)
|
|
||||||
final_time = Time.now
|
|
||||||
|
|
||||||
Rails.logger.warn "[BENCHMARK] Compilation:\t#{(compiled_time - start) * 1000.0}ms"
|
ActiveSupport::JSON.encode(compiled_template.render)
|
||||||
Rails.logger.warn "[BENCHMARK] Rendering:\t\t#{(render_time - compiled_time) * 1000.0}ms"
|
|
||||||
Rails.logger.warn "[BENCHMARK] JSON encoding:\t#{(final_time - render_time) * 1000.0}ms"
|
|
||||||
Rails.logger.warn "[BENCHMARK] Total:\t\t#{(final_time - start) * 1000.0}ms"
|
|
||||||
|
|
||||||
res
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_compiled_template(path, source, context)
|
def get_compiled_template(path, source, context)
|
||||||
#@cached_templates[path] ||=
|
@cached_templates[path] ||= Compiler.new(context).compile_source(source)
|
||||||
Compiler.new(context).compile_source(source)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(path)
|
def get(path, context)
|
||||||
template = @cached_templates[path]
|
template = @cached_templates[path]
|
||||||
return template if !template.nil?
|
return template if !template.nil?
|
||||||
t = @view_renderer.lookup_context.find_template(path, [], false)
|
t = @view_renderer.lookup_context.find_template(path, [], false)
|
||||||
get_compiled_template(path, t.source, nil)
|
get_compiled_template(path, t.source, context)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -24,21 +24,24 @@ module RablFastJson
|
|||||||
|
|
||||||
source.inject({}) { |output, current|
|
source.inject({}) { |output, current|
|
||||||
key, value = current
|
key, value = current
|
||||||
|
|
||||||
out = case value
|
out = case value
|
||||||
when Symbol
|
when Symbol
|
||||||
data.send(value) # attributes
|
data.send(value) # attributes
|
||||||
when Proc
|
when Proc
|
||||||
value.call(data) # node
|
value.call(data) # node
|
||||||
when Hash
|
when Hash
|
||||||
data_symbol = value.delete(:_data)
|
current_value = value.dup
|
||||||
object = data_symbol.to_s.start_with?('@') ? @context.instance_variable_get(data_symbol) : @object.send(data_symbol)
|
data_symbol = current_value.delete(:_data)
|
||||||
|
object = data_symbol.nil? ? data : data_symbol.to_s.start_with?('@') ? @context.instance_variable_get(data_symbol) : data.send(data_symbol)
|
||||||
|
|
||||||
if key.to_s.start_with?('_') # glue
|
if key.to_s.start_with?('_') # glue
|
||||||
value.each_pair { |k, v|
|
current_value.each_pair { |k, v|
|
||||||
output[k] = object.send(v)
|
output[k] = object.send(v)
|
||||||
}
|
}
|
||||||
next output
|
next output
|
||||||
else # child
|
else # child
|
||||||
object.respond_to?(:each) ? render_collection(object, value) : render_resource(object, value)
|
object.respond_to?(:each) ? render_collection(object, current_value) : render_resource(object, current_value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
output[key] = out
|
output[key] = out
|
||||||
|
@ -87,9 +87,9 @@ class CompilerTest < ActiveSupport::TestCase
|
|||||||
assert_equal :users, t.root_name
|
assert_equal :users, t.root_name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "extends use other template one's active" do
|
test "extends use other template source as itself" do
|
||||||
template = mock('template', :source => { :id => :id })
|
template = mock('template', :source => { :id => :id })
|
||||||
RablFastJson::Library.stub_chain(:instance, :get).with('users/base').and_return(template)
|
RablFastJson::Library.instance.stub(:get).with('users/base', @context).and_return(template)
|
||||||
t = @compiler.compile_source(%{ extends 'users/base' })
|
t = @compiler.compile_source(%{ extends 'users/base' })
|
||||||
assert_equal({ :id => :id }, t.source)
|
assert_equal({ :id => :id }, t.source)
|
||||||
end
|
end
|
||||||
|
61
test/deep_nesting_test.rb
Normal file
61
test/deep_nesting_test.rb
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class DeepNestingTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
|
class Post
|
||||||
|
attr_accessor :id, :title
|
||||||
|
|
||||||
|
def initialize(id, title)
|
||||||
|
@id, @title = id, title
|
||||||
|
end
|
||||||
|
|
||||||
|
def comments
|
||||||
|
[Struct.new(:id, :content).new(1, 'first'), Struct.new(:id, :content).new(2, 'second')]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
setup do
|
||||||
|
RablFastJson::Library.reset_instance
|
||||||
|
@post = Post.new(42, 'I rock !')
|
||||||
|
@user = User.new(1, 'foobar', 'male')
|
||||||
|
@user.stub(:posts).and_return([@post])
|
||||||
|
@user.stub(:respond_to?).with(:each).and_return(false)
|
||||||
|
|
||||||
|
@view_renderer = mock()
|
||||||
|
@view_renderer.stub_chain(:lookup_context, :find_template).with('comments/show', [], false).and_return(
|
||||||
|
mock(:source => %{ object :@comment\n attribute :content }))
|
||||||
|
|
||||||
|
@context = Context.new
|
||||||
|
@context.stub(:instance_variable_get).with(:@user).and_return(@user)
|
||||||
|
@context.stub(:instance_variable_get).with(:@view_renderer).and_return(@view_renderer)
|
||||||
|
@context.stub(:instance_variable_get).with(:@virtual_path).and_return('users/show')
|
||||||
|
end
|
||||||
|
|
||||||
|
test "compile and render deep nesting template" do
|
||||||
|
source = %{
|
||||||
|
object :@user
|
||||||
|
attributes :id, :name
|
||||||
|
child :posts do
|
||||||
|
attribute :title
|
||||||
|
child :comments do
|
||||||
|
extends 'comments/show'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(ActiveSupport::JSON.encode({
|
||||||
|
:id => 1,
|
||||||
|
:name => 'foobar',
|
||||||
|
:posts => [{
|
||||||
|
:title => 'I rock !',
|
||||||
|
:comments => [
|
||||||
|
{ :content => 'first' },
|
||||||
|
{ :content => 'second' }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}), RablFastJson::Library.instance.get_rendered_template(source, @context))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,6 +5,21 @@ $:.unshift File.expand_path('../../lib', __FILE__)
|
|||||||
require 'rspec/mocks'
|
require 'rspec/mocks'
|
||||||
require 'minitest/autorun'
|
require 'minitest/autorun'
|
||||||
require 'active_support/test_case'
|
require 'active_support/test_case'
|
||||||
|
|
||||||
|
require 'singleton'
|
||||||
|
class <<Singleton
|
||||||
|
def included_with_reset(klass)
|
||||||
|
included_without_reset(klass)
|
||||||
|
class <<klass
|
||||||
|
def reset_instance
|
||||||
|
Singleton.send :__init__, self
|
||||||
|
self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
alias_method_chain :included, :reset
|
||||||
|
end
|
||||||
|
|
||||||
require 'rabl-fast-json'
|
require 'rabl-fast-json'
|
||||||
|
|
||||||
module ActiveSupport
|
module ActiveSupport
|
||||||
|
Loading…
Reference in New Issue
Block a user