Repository: Shopify/liquid (Ruby)

Issue:
Include fails if strict_variables
When a template is rendered with `strict_variables: true` and the template includes a simple `include` like so:

```liquid
{% include "some_temploate" %}
```

a Liquid::UndefinedVariable is raised.

This is because of the "default name" feature where a variable is automatically assigned to the included template if the variable has the same name as the template.

Am I right that it should be possible in this case to look up a variable but now raise an error if not found and `:strict_variables` is set?
If so I will be happy to provide a PR.


Discussion:
Edit: The UndefinedVariable is not raised, but added to the `errors` attribute of the template.



Patch:
diff --git a/History.md b/History.md
index 68db09658..99bc45705 100644
--- a/History.md
+++ b/History.md
@@ -22,6 +22,7 @@
 * Liquid::Template.register_filter raises when the module overrides registered public methods as private or protected (#705) [Gaurav Chande]
 
 ### Fixed
+* Fix include tag used with strict_variables (#828) [QuickPay]
 * Fix map filter when value is a Proc (#672) [Guillaume Malette]
 * Fix truncate filter when value is not a string (#672) [Guillaume Malette]
 * Fix behaviour of escape filter when input is nil (#665) [Tanel Jakobsoo]
diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb
index 769282124..cd9aadfa5 100644
--- a/lib/liquid/context.rb
+++ b/lib/liquid/context.rb
@@ -180,7 +180,7 @@ def evaluate(object)
     end
 
     # Fetches an object starting at the local scope and then moving up the hierachy
-    def find_variable(key)
+    def find_variable(key, raise_on_not_found: true)
       # This was changed from find() to find_index() because this is a very hot
       # path and find_index() is optimized in MRI to reduce object allocation
       index = @scopes.find_index { |s| s.key?(key) }
@@ -190,7 +190,7 @@ def find_variable(key)
 
       if scope.nil?
         @environments.each do |e|
-          variable = lookup_and_evaluate(e, key)
+          variable = lookup_and_evaluate(e, key, raise_on_not_found: raise_on_not_found)
           unless variable.nil?
             scope = e
             break
@@ -199,7 +199,7 @@ def find_variable(key)
       end
 
       scope ||= @environments.last || @scopes.last
-      variable ||= lookup_and_evaluate(scope, key)
+      variable ||= lookup_and_evaluate(scope, key, raise_on_not_found: raise_on_not_found)
 
       variable = variable.to_liquid
       variable.context = self if variable.respond_to?(:context=)
@@ -207,8 +207,8 @@ def find_variable(key)
       variable
     end
 
-    def lookup_and_evaluate(obj, key)
-      if @strict_variables && obj.respond_to?(:key?) && !obj.key?(key)
+    def lookup_and_evaluate(obj, key, raise_on_not_found: true)
+      if @strict_variables && raise_on_not_found && obj.respond_to?(:key?) && !obj.key?(key)
         raise Liquid::UndefinedVariable, "undefined variable #{key}"
       end
 
diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb
index 9234eb437..a80070362 100644
--- a/lib/liquid/tags/include.rb
+++ b/lib/liquid/tags/include.rb
@@ -50,7 +50,7 @@ def render(context)
       variable = if @variable_name_expr
         context.evaluate(@variable_name_expr)
       else
-        context.find_variable(template_name)
+        context.find_variable(template_name, raise_on_not_found: false)
       end
 
       old_template_name = context.template_name


Test patch:
diff --git a/test/integration/tags/include_tag_test.rb b/test/integration/tags/include_tag_test.rb
index 7b4e3f6d2..25af66285 100644
--- a/test/integration/tags/include_tag_test.rb
+++ b/test/integration/tags/include_tag_test.rb
@@ -235,4 +235,11 @@ def test_including_via_variable_value
 
     assert_template_result "Product: Draft 151cm ", "{% assign page = 'product' %}{% include page for foo %}", "foo" => { 'title' => 'Draft 151cm' }
   end
+
+  def test_including_with_strict_variables
+    template = Liquid::Template.parse("{% include 'simple' %}", error_mode: :warn)
+    template.render(nil, strict_variables: true)
+
+    assert_equal [], template.errors
+  end
 end # IncludeTagTest