Skip to content

Commit

Permalink
Merge pull request #2572 from elsurudo/liquid-group-by-tag
Browse files Browse the repository at this point in the history
Add `group_by` liquid filter
  • Loading branch information
dsander committed Aug 1, 2019
2 parents 93e72a6 + b8e5e53 commit 44cab36
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
21 changes: 21 additions & 0 deletions app/concerns/liquid_interpolatable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,27 @@ def as_object(object)
throw :as_object, object.as_json
end

# Group an array of items by a property
#
# Example usage:
#
# {% assign posts_by_author = site.posts | group_by: "author" %}
# {% for author in posts_by_author %}
# <dt>{{author.name}}</dt>
# {% for post in author.items %}
# <dd><a href="{{post.url}}">{{post.title}}</a></dd>
# {% endfor %}
# {% endfor %}
def group_by(input, property)
if input.respond_to?(:group_by)
input.group_by { |item| item[property] }.map do |value, items|
{ 'name' => value, 'items' => items }
end
else
input
end
end

private

def logger
Expand Down
42 changes: 39 additions & 3 deletions spec/concerns/liquid_interpolatable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,19 @@ def @filter.to_xpath_roundtrip(string)
@agent.interpolation_context['s'] = 'http://example.com/dir/1?q=test'
end

it 'should parse an abosule URI' do
it 'should parse an absolute URI' do
expect(@filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1')).to eq(URI('http://example.net/index.html'))
end

it 'should parse an abosule URI with a base URI specified' do
it 'should parse an absolute URI with a base URI specified' do
expect(@filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1')).to eq(URI('http://example.net/index.html'))
end

it 'should parse a relative URI with a base URI specified' do
expect(@filter.to_uri('foo/index.html', 'http://example.com/dir/1')).to eq(URI('http://example.com/dir/foo/index.html'))
end

it 'should parse an abosule URI with a base URI specified' do
it 'should parse an absolute URI with a base URI specified' do
expect(@filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1')).to eq(URI('http://example.net/index.html'))
end

Expand Down Expand Up @@ -394,4 +394,40 @@ def ensure_safety(obj)
expect(agent.interpolated['template']).to eq('38b98bc2625a8cac33369f6204e784482be5e172b242699406270856a841d1ec')
end
end

describe 'group_by' do
let(:events) do
[
{ "date" => "2019-07-30", "type" => "Snap" },
{ "date" => "2019-07-30", "type" => "Crackle" },
{ "date" => "2019-07-29", "type" => "Pop" },
{ "date" => "2019-07-29", "type" => "Bam" },
{ "date" => "2019-07-29", "type" => "Pow" },
]
end

it "should group an enumerable by the given attribute" do
expect(@filter.group_by(events, "date")).to eq(
[
{
"name" => "2019-07-30", "items" => [
{ "date" => "2019-07-30", "type" => "Snap" },
{ "date" => "2019-07-30", "type" => "Crackle" }
]
},
{
"name" => "2019-07-29", "items" => [
{ "date" => "2019-07-29", "type" => "Pop" },
{ "date" => "2019-07-29", "type" => "Bam" },
{ "date" => "2019-07-29", "type" => "Pow" }
]
}
]
)
end

it "should leave non-groupables alone" do
expect(@filter.group_by("some string", "anything")).to eq("some string")
end
end
end

0 comments on commit 44cab36

Please sign in to comment.