Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/liquid/self_drop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@ module Liquid
# then the local value takes precedence over the `self` object.
# @liquid_access global
class SelfDrop < Drop
def initialize(context)
def initialize(self_context)
super()
@context = context
@self_context = self_context
end

def [](key)
@context.find_variable(key)
@self_context.find_variable(key)
rescue UndefinedVariable
nil
end

def key?(key)
@context.variable_defined?(key)
@self_context.variable_defined?(key)
end

def context=(_); end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def context=(_); end
undef context

this should be done so upstream implementations know the value is not contextualizable


def to_liquid
self
end
Expand Down
91 changes: 91 additions & 0 deletions test/integration/self_drop_context_test.rb
Comment thread
karreiro marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# frozen_string_literal: true

require 'test_helper'

class SelfDropContextTest < Minitest::Test
include Liquid

def test_self_drop_passed_as_render_param_preserves_original_scope
source = <<~LIQUID
{%- assign var = 42 -%}
{%- assign s = self -%}
{%- render "snippet1", other_self: s -%}
LIQUID

partials = {
'snippet1' => <<~LIQUID,
{%- assign var = 43 -%}
{{- other_self.var }}|{{ self.var -}}
LIQUID
}

assert_template_result('42|43', source, partials: partials)
end

def test_self_drop_in_render_without_passing_resolves_inner_scope
source = <<~LIQUID
{%- assign var = 42 -%}
{%- render "snippet1" -%}
LIQUID

partials = {
'snippet1' => <<~LIQUID,
{%- assign var = 99 -%}
{{- self.var -}}
LIQUID
}

assert_template_result('99', source, partials: partials)
end

def test_self_drop_passed_to_nested_renders_preserves_each_level
source = <<~LIQUID
{%- assign a = 1 -%}
{%- assign s1 = self -%}
{%- render "snippet1", outer: s1 -%}
LIQUID

partials = {
'snippet1' => <<~LIQUID,
{%- assign a = 2 -%}
{%- assign s2 = self -%}
{%- render "snippet2", outer: outer, middle: s2 -%}
LIQUID
'snippet2' => <<~LIQUID,
{%- assign a = 3 -%}
{{- outer.a }}|{{ middle.a }}|{{ self.a -}}
LIQUID
}

assert_template_result('1|2|3', source, partials: partials)
end

def test_self_drop_reflects_variables_assigned_after_creation
source = <<~LIQUID
{%- assign s = self -%}
{%- assign x = 42 %}{{ s.x -}}
LIQUID

assert_template_result('42', source)
end

def test_self_drop_context_writer_is_a_noop
context = Context.new
drop = SelfDrop.new(context)
assert(drop.respond_to?(:context=))
drop.context = Context.new
assert_nil(drop.instance_variable_get(:@context))
end

def test_self_drop_with_strict_variables_does_not_raise_for_defined_var
t = Template.parse('{{ self.x }}')
result = t.render({ 'x' => 42 }, strict_variables: true)
assert_equal('42', result)
end

def test_self_drop_with_strict_variables_returns_nil_for_undefined_var
t = Template.parse('{{ self.x }}')
result = t.render({}, strict_variables: true)
assert_equal('', result)
end
end
Loading