Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update variable's context before invoking its to_liquid #1781

Merged
merged 2 commits into from Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Expand Up @@ -23,6 +23,6 @@ group :test do
gem 'rubocop-performance', require: false

platform :mri, :truffleruby do
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'master'
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'main'
end
end
8 changes: 6 additions & 2 deletions lib/liquid/context.rb
Expand Up @@ -197,10 +197,14 @@ def find_variable(key, raise_on_not_found: true)
try_variable_find_in_environments(key, raise_on_not_found: raise_on_not_found)
end

variable = variable.to_liquid
# update variable's context before invoking #to_liquid
variable.context = self if variable.respond_to?(:context=)

variable
liquid_variable = variable.to_liquid

liquid_variable.context = self if variable != liquid_variable && liquid_variable.respond_to?(:context=)

liquid_variable
end

def lookup_and_evaluate(obj, key, raise_on_not_found: true)
Expand Down
37 changes: 37 additions & 0 deletions test/integration/context_test.rb
Expand Up @@ -36,6 +36,24 @@ def to_liquid
end
end

class ProductsDrop < Liquid::Drop
def initialize(products)
@products = products
end

def size
@products.size
end

def to_liquid
if @context["forloop"]
@products.first(@context["forloop"].length)
else
@products
end
end
end

class CategoryDrop < Liquid::Drop
attr_accessor :category, :context

Expand Down Expand Up @@ -635,6 +653,25 @@ def test_context_always_uses_static_registers
assert_equal(:my_value, c.registers[:my_register])
end

def test_variable_to_liquid_returns_contextual_drop
context = {
"products" => ProductsDrop.new(["A", "B", "C", "D", "E"]),
}

template = Liquid::Template.parse(<<~LIQUID)
{%- for i in (1..3) -%}
for_loop_products_count: {{ products | size }}
{% endfor %}

unscoped_products_count: {{ products | size }}
LIQUID

result = template.render(context)

assert_includes(result, "for_loop_products_count: 3")
assert_includes(result, "unscoped_products_count: 5")
end

private

def assert_no_object_allocations
Expand Down