diff --git a/lib/liquid/htmltags.rb b/lib/liquid/htmltags.rb
index 05b0419..8ceab44 100644
--- a/lib/liquid/htmltags.rb
+++ b/lib/liquid/htmltags.rb
@@ -23,7 +23,7 @@ module Liquid
from = @attributes['offset'] ? context[@attributes['offset']].to_i : 0
to = @attributes['limit'] ? from + context[@attributes['limit']].to_i : nil
- collection = Utils.slice_collection_using_each(collection, from, to)
+ collection = Utils.slice_collection(collection, from, to)
length = collection.length
diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb
index 5902704..9955b5e 100644
--- a/lib/liquid/tags/for.rb
+++ b/lib/liquid/tags/for.rb
@@ -75,8 +75,7 @@ module Liquid
limit = context[@attributes['limit']]
to = limit ? limit.to_i + from : nil
-
- segment = Utils.slice_collection_using_each(collection, from, to)
+ segment = Utils.slice_collection(collection, from, to)
return render_else(context) if segment.empty?
diff --git a/lib/liquid/utils.rb b/lib/liquid/utils.rb
index 0bf6df2..cb96524 100644
--- a/lib/liquid/utils.rb
+++ b/lib/liquid/utils.rb
@@ -1,5 +1,18 @@
module Liquid
module Utils
+
+ def self.slice_collection(collection, from, to)
+ if (from != 0 || to != nil) && collection.respond_to?(:load_slice)
+ collection.load_slice(from, to)
+ else
+ slice_collection_using_each(collection, from, to)
+ end
+ end
+
+ def self.non_blank_string?(collection)
+ collection.is_a?(String) && collection != ''
+ end
+
def self.slice_collection_using_each(collection, from, to)
segments = []
index = 0
@@ -22,9 +35,5 @@ module Liquid
segments
end
-
- def self.non_blank_string?(collection)
- collection.is_a?(String) && collection != ''
- end
end
end
diff --git a/test/liquid/tags/for_tag_test.rb b/test/liquid/tags/for_tag_test.rb
index 9186d3f..4dde8a4 100644
--- a/test/liquid/tags/for_tag_test.rb
+++ b/test/liquid/tags/for_tag_test.rb
@@ -294,4 +294,62 @@ HERE
assigns = {'items' => [1,2,3,4,5]}
assert_template_result(expected, template, assigns)
end
+
+ class LoaderDrop < Liquid::Drop
+ attr_accessor :each_called, :load_slice_called
+
+ def initialize(data)
+ @data = data
+ end
+
+ def each
+ @each_called = true
+ @data.each { |el| yield el }
+ end
+
+ def load_slice(from, to)
+ @load_slice_called = true
+ @data[(from..to-1)]
+ end
+ end
+
+ def test_iterate_with_each_when_no_limit_applied
+ loader = LoaderDrop.new([1,2,3,4,5])
+ assigns = {'items' => loader}
+ expected = '12345'
+ template = '{% for item in items %}{{item}}{% endfor %}'
+ assert_template_result(expected, template, assigns)
+ assert loader.each_called
+ assert !loader.load_slice_called
+ end
+
+ def test_iterate_with_load_slice_when_limit_applied
+ loader = LoaderDrop.new([1,2,3,4,5])
+ assigns = {'items' => loader}
+ expected = '1'
+ template = '{% for item in items limit:1 %}{{item}}{% endfor %}'
+ assert_template_result(expected, template, assigns)
+ assert !loader.each_called
+ assert loader.load_slice_called
+ end
+
+ def test_iterate_with_load_slice_when_limit_and_offset_applied
+ loader = LoaderDrop.new([1,2,3,4,5])
+ assigns = {'items' => loader}
+ expected = '34'
+ template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}'
+ assert_template_result(expected, template, assigns)
+ assert !loader.each_called
+ assert loader.load_slice_called
+ end
+
+ def test_iterate_with_load_slice_returns_same_results_as_without
+ loader = LoaderDrop.new([1,2,3,4,5])
+ loader_assigns = {'items' => loader}
+ array_assigns = {'items' => [1,2,3,4,5]}
+ expected = '34'
+ template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}'
+ assert_template_result(expected, template, loader_assigns)
+ assert_template_result(expected, template, array_assigns)
+ end
end