mirror of
https://github.com/kemko/liquid.git
synced 2026-01-04 17:25:41 +03:00
Templates and Contexts differentiate between different sources of assigns
This commit is contained in:
@@ -14,13 +14,15 @@ module Liquid
|
||||
# context['bob'] #=> nil class Context
|
||||
class Context
|
||||
attr_reader :scopes
|
||||
attr_reader :errors, :registers
|
||||
attr_reader :errors, :registers, :environment
|
||||
|
||||
def initialize(assigns = {}, registers = {}, rethrow_errors = false)
|
||||
@scopes = [(assigns || {})]
|
||||
@registers = registers
|
||||
@errors = []
|
||||
def initialize(environment = {}, instance_assigns = {}, registers = {}, rethrow_errors = false)
|
||||
@environment = environment
|
||||
@scopes = [(instance_assigns || {})]
|
||||
@registers = registers
|
||||
@errors = []
|
||||
@rethrow_errors = rethrow_errors
|
||||
squash_instance_assigns_with_environment
|
||||
end
|
||||
|
||||
def strainer
|
||||
@@ -61,9 +63,9 @@ module Liquid
|
||||
end
|
||||
|
||||
# push new local scope on the stack. use <tt>Context#stack</tt> instead
|
||||
def push
|
||||
def push(new_scope={})
|
||||
raise StackLevelError, "Nesting too deep" if @scopes.length > 100
|
||||
@scopes.unshift({})
|
||||
@scopes.unshift(new_scope)
|
||||
end
|
||||
|
||||
# merge a hash of variables in the current local scope
|
||||
@@ -86,9 +88,9 @@ module Liquid
|
||||
# end
|
||||
# context['var] #=> nil
|
||||
#
|
||||
def stack(&block)
|
||||
def stack(new_scope={},&block)
|
||||
result = nil
|
||||
push
|
||||
push(new_scope)
|
||||
begin
|
||||
result = yield
|
||||
ensure
|
||||
@@ -96,6 +98,10 @@ module Liquid
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def clear_instance_assigns
|
||||
@scopes[0] = {}
|
||||
end
|
||||
|
||||
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
|
||||
def []=(key, value)
|
||||
@@ -156,9 +162,14 @@ module Liquid
|
||||
# fetches an object starting at the local scope and then moving up
|
||||
# the hierachy
|
||||
def find_variable(key)
|
||||
scope = @scopes[0..-2].find { |s| s.has_key?(key) } || @scopes.last
|
||||
variable = scope[key]
|
||||
variable = scope[key] = variable.call(self) if variable.is_a?(Proc)
|
||||
scope = @scopes.find { |s| s.has_key?(key) } || environment
|
||||
|
||||
if scope[key].is_a?(Proc)
|
||||
variable = scope[key] = scope[key].call(self)
|
||||
else
|
||||
variable = scope[key]
|
||||
end
|
||||
|
||||
variable = variable.to_liquid
|
||||
variable.context = self if variable.respond_to?(:context=)
|
||||
return variable
|
||||
@@ -217,5 +228,14 @@ module Liquid
|
||||
|
||||
object
|
||||
end
|
||||
|
||||
def squash_instance_assigns_with_environment
|
||||
scopes[0].each_key do |k|
|
||||
if environment.has_key?(k)
|
||||
scopes[0][k] = environment[k]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -67,6 +67,10 @@ module Liquid
|
||||
@assigns ||= {}
|
||||
end
|
||||
|
||||
def instance_assigns
|
||||
@instance_assigns ||= {}
|
||||
end
|
||||
|
||||
def errors
|
||||
@errors ||= []
|
||||
end
|
||||
@@ -84,16 +88,17 @@ module Liquid
|
||||
#
|
||||
def render(*args)
|
||||
return '' if @root.nil?
|
||||
|
||||
|
||||
context = case args.first
|
||||
when Liquid::Context
|
||||
args.shift
|
||||
when Hash
|
||||
a = args.shift
|
||||
assigns.each { |k,v| a[k] = v unless a.has_key?(k) }
|
||||
Context.new(a, registers, @rethrow_errors)
|
||||
environment = args.shift
|
||||
environment.merge!(assigns) {|k,v1,v2| v1}
|
||||
Context.new(environment, instance_assigns, registers, @rethrow_errors)
|
||||
when nil
|
||||
Context.new(assigns.dup, registers, @rethrow_errors)
|
||||
environment = assigns.dup
|
||||
Context.new(environment, instance_assigns, registers, @rethrow_errors)
|
||||
else
|
||||
raise ArgumentError, "Expect Hash or Liquid::Context as parameter"
|
||||
end
|
||||
|
||||
@@ -23,4 +23,35 @@ class TemplateTest < Test::Unit::TestCase
|
||||
assert_equal [' ', '{% comment %}', ' ', '{% endcomment %}', ' '], Template.new.send(:tokenize, " {% comment %} {% endcomment %} ")
|
||||
end
|
||||
|
||||
def test_instance_assigns_persist_on_same_template_object_between_parses
|
||||
t = Template.new
|
||||
assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render
|
||||
assert_equal 'from instance assigns', t.parse("{{ foo }}").render
|
||||
end
|
||||
|
||||
def test_instance_assigns_persist_on_same_template_parsing_between_renders
|
||||
t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
|
||||
assert_equal 'foo', t.render
|
||||
assert_equal 'foofoo', t.render
|
||||
end
|
||||
|
||||
def test_custom_assigns_do_not_persist_on_same_template
|
||||
t = Template.new
|
||||
assert_equal 'from custom assigns', t.parse("{{ foo }}").render('foo' => 'from custom assigns')
|
||||
assert_equal '', t.parse("{{ foo }}").render
|
||||
end
|
||||
|
||||
def test_custom_assigns_squash_instance_assigns
|
||||
t = Template.new
|
||||
assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render
|
||||
assert_equal 'from custom assigns', t.parse("{{ foo }}").render('foo' => 'from custom assigns')
|
||||
end
|
||||
|
||||
def test_persistent_assigns_squash_instance_assigns
|
||||
t = Template.new
|
||||
assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render
|
||||
t.assigns['foo'] = 'from persistent assigns'
|
||||
assert_equal 'from persistent assigns', t.parse("{{ foo }}").render
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user