Skip to content

Commit

Permalink
Resolves #529. Resolves #404. Added natural sorting filter and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
arthanzel committed May 4, 2015
1 parent 251ce74 commit 03b3446
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
21 changes: 21 additions & 0 deletions lib/liquid/standardfilters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,27 @@ def sort(input, property = nil)
end
end

# Sort elements of an array ignoring case if strings
# provide optional property with which to sort an array of hashes or drops
def sort_natural(input, property = nil)
ary = InputIterator.new(input)

# Quick function that returns the downcased object if it has a downcase,
# otherwise it returns the object itself.
insensitive = lambda do |obj|
obj = obj.downcase if obj.respond_to? :downcase
obj
end

if property.nil?
ary.sort {|a,b| insensitive.call(a) <=> insensitive.call(b) }
elsif ary.first.respond_to?(:[]) && !ary.first[property].nil?
ary.sort {|a,b| insensitive.call(a[property]) <=> insensitive.call(b[property]) }
elsif ary.first.respond_to?(property)
ary.sort {|a,b| insensitive.call(a.send(property)) <=> insensitive.call(b.send(property)) }
end
end

# Remove duplicate elements from an array
# provide optional property with which to determine uniqueness
def uniq(input, property = nil)
Expand Down
36 changes: 36 additions & 0 deletions test/integration/filter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,38 @@ def test_sort
@context['numbers'] = [2,1,4,3]
@context['words'] = ['expected', 'as', 'alphabetic']
@context['arrays'] = ['flower', 'are']
@context['case_sensitive'] = ['sensitive', 'Expected', 'case']

assert_equal [1,2,3,4], Variable.new("numbers | sort").render(@context)
assert_equal ['alphabetic', 'as', 'expected'], Variable.new("words | sort").render(@context)
assert_equal [3], Variable.new("value | sort").render(@context)
assert_equal ['are', 'flower'], Variable.new("arrays | sort").render(@context)
assert_equal ['Expected', 'case', 'sensitive'], Variable.new("case_sensitive | sort").render(@context)
end

def test_sort_natural
@context['value'] = 3
@context['numbers'] = [2,1,4,3]
@context['words'] = ['case', 'Assert', 'Insensitive']
# This specific syntax forces hashes to have string keys. Colons won't work.
@context['hashes'] = [{ 'a' => 'A'}, { 'a' => 'b'}, { 'a' => 'C' }]
@context['objects'] = [TestObject.new('A'), TestObject.new('b'), TestObject.new('C')]

assert_equal [1,2,3,4], Variable.new("numbers | sort_natural").render(@context)
assert_equal ['Assert', 'case', 'Insensitive'], Variable.new("words | sort_natural").render(@context)
assert_equal [3], Variable.new("value | sort_natural").render(@context)

# Test hashes
sorted = Variable.new("hashes | sort_natural: 'a'").render(@context)
assert_equal sorted[0]['a'], 'A'
assert_equal sorted[1]['a'], 'b'
assert_equal sorted[2]['a'], 'C'

# Test objects
sorted = Variable.new("objects | sort_natural: 'a'").render(@context)
assert_equal sorted[0].a, 'A'
assert_equal sorted[1].a, 'b'
assert_equal sorted[2].a, 'C'
end

def test_strip_html
Expand Down Expand Up @@ -136,3 +163,12 @@ def test_local_filter_with_deprecated_syntax
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, [CanadianMoneyFilter])
end
end # FiltersTest

# Simple object that may be passed into a filter.
# Note to test subjects: do not smuggle test objects out of the testing area.
class TestObject
attr_accessor :a
def initialize(a)
@a = a
end
end

0 comments on commit 03b3446

Please sign in to comment.