Fix deep nesting case
This commit is contained in:
parent
844b2703e2
commit
1a033a60c2
@ -1,7 +1,7 @@
|
||||
module RablFastJson
|
||||
class Compiler
|
||||
|
||||
def initialize(context = nil, assigns = nil)
|
||||
def initialize(context = nil)
|
||||
@context = context
|
||||
@glue_count = 0
|
||||
end
|
||||
@ -50,7 +50,7 @@ module RablFastJson
|
||||
end
|
||||
|
||||
def extends(path)
|
||||
t = Library.instance.get(path)
|
||||
t = Library.instance.get(path, @context)
|
||||
@template.merge!(t.source)
|
||||
end
|
||||
|
||||
@ -77,7 +77,7 @@ module RablFastJson
|
||||
end
|
||||
|
||||
def _compile_sub_template(name, data, &block)
|
||||
compiler = Compiler.new(@context, @assigns)
|
||||
compiler = Compiler.new(@context)
|
||||
template = compiler.compile_block(&block)
|
||||
@template[name] = template.merge!(:_data => data)
|
||||
end
|
||||
|
@ -11,33 +11,22 @@ module RablFastJson
|
||||
def get_rendered_template(source, context)
|
||||
path = context.instance_variable_get(:@virtual_path)
|
||||
@view_renderer = context.instance_variable_get(:@view_renderer)
|
||||
start = Time.now
|
||||
|
||||
compiled_template = get_compiled_template(path, source, context)
|
||||
compiled_time = Time.now
|
||||
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"
|
||||
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
|
||||
ActiveSupport::JSON.encode(compiled_template.render)
|
||||
end
|
||||
|
||||
def get_compiled_template(path, source, context)
|
||||
#@cached_templates[path] ||=
|
||||
Compiler.new(context).compile_source(source)
|
||||
@cached_templates[path] ||= Compiler.new(context).compile_source(source)
|
||||
end
|
||||
|
||||
def get(path)
|
||||
def get(path, context)
|
||||
template = @cached_templates[path]
|
||||
return template if !template.nil?
|
||||
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
|
@ -24,21 +24,24 @@ module RablFastJson
|
||||
|
||||
source.inject({}) { |output, current|
|
||||
key, value = current
|
||||
|
||||
out = case value
|
||||
when Symbol
|
||||
data.send(value) # attributes
|
||||
when Proc
|
||||
value.call(data) # node
|
||||
when Hash
|
||||
data_symbol = value.delete(:_data)
|
||||
object = data_symbol.to_s.start_with?('@') ? @context.instance_variable_get(data_symbol) : @object.send(data_symbol)
|
||||
current_value = value.dup
|
||||
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
|
||||
value.each_pair { |k, v|
|
||||
current_value.each_pair { |k, v|
|
||||
output[k] = object.send(v)
|
||||
}
|
||||
next output
|
||||
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
|
||||
output[key] = out
|
||||
|
@ -87,9 +87,9 @@ class CompilerTest < ActiveSupport::TestCase
|
||||
assert_equal :users, t.root_name
|
||||
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 })
|
||||
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' })
|
||||
assert_equal({ :id => :id }, t.source)
|
||||
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 'minitest/autorun'
|
||||
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'
|
||||
|
||||
module ActiveSupport
|
||||
|
Loading…
Reference in New Issue
Block a user