Skip to content

Loading…

Enumerate any object tagged with Mustache::Enumerable. #136

Merged
merged 3 commits into from

4 participants

@nuclearsandwich

This commit adds a module called Mustache::Enumerable which is a
method of signalling to the Mustache generator which enumerable objects
should be treated as arrays and which should be left alone.

To use it, create an object for Mustache to use as an array such as a
People class. Then include the Mustache::Enumerable module. As long as
your class is actually enumerable it will work as you expect.

Tagging with a custom module was preferred to checking for any
enumerable object since it can cause counter-intuitive behavior in
objects like Structs.

For an example of use see
MustacheTest#test_enumerable_sections_enumerate_mustache_enumerables
test/mustache_test.rb

This is a more heavyweight solution than the alternative I presented in
issue #93.

@nuclearsandwich nuclearsandwich Enumerate any object tagged with Mustache::Enumerable.
This commit adds a module called `Mustache::Enumerable` which is a
method of signalling to the Mustache generator which enumerable objects
should be treated as arrays and which should be left alone.

To use it, create an object for Mustache to use as an array such as a
People class. Then include the Mustache::Enumerable module. As long as
your class is actually enumerable it will work as you expect.

Tagging with a custom module was preferred to checking for any
enumerable object since it can cause counter-intuitive behavior in
objects like Structs.

For an example of use see
`MustacheTest#test_enumerable_sections_enumerate_mustache_enumerables`
test/mustache_test.rb

This is a more heavyweight solution than the alternative I presented in
issue #93.
2a6d8e7
@brntbeer

:+1: for this.

Maybe I'm bad at mustache, but every time I have an active record relation it doesn't iterate correctly, and it makes me cry.

@halorgium

:+1: This also resolves issues with ActiveRecord::Relation iteration.

I would also suggest that including this Module into Array and Enumerator (if present) would also be cleaner.

@locks locks commented on an outdated diff
test/mustache_test.rb
@@ -344,6 +344,63 @@ def test_enumerable_sections_accept_a_string_keyed_hash_as_a_context
assert_equal ' <li>1234</li> ', instance.render
end
+ def test_enumerable_sections_enumerate_mustache_enumerables
@locks Mustache member
locks added a note

what's with the wonky indentation?

It was a brand new Macbook and I'd yet to configure Vim properly. I'll do what I can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@locks
Mustache member

Could you fix the indentation problems? I'll consider this PR meanwhile.

@locks
Mustache member
@nuclearsandwich

Sorry. School sucks :school_satchel:.

@locks
Mustache member

I know the feeling! Thank you for the time.

@locks locks merged commit 70bc503 into mustache:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 15, 2012
  1. @nuclearsandwich

    Enumerate any object tagged with Mustache::Enumerable.

    nuclearsandwich committed
    This commit adds a module called `Mustache::Enumerable` which is a
    method of signalling to the Mustache generator which enumerable objects
    should be treated as arrays and which should be left alone.
    
    To use it, create an object for Mustache to use as an array such as a
    People class. Then include the Mustache::Enumerable module. As long as
    your class is actually enumerable it will work as you expect.
    
    Tagging with a custom module was preferred to checking for any
    enumerable object since it can cause counter-intuitive behavior in
    objects like Structs.
    
    For an example of use see
    `MustacheTest#test_enumerable_sections_enumerate_mustache_enumerables`
    test/mustache_test.rb
    
    This is a more heavyweight solution than the alternative I presented in
    issue #93.
Commits on Apr 17, 2014
  1. @nuclearsandwich

    Fix wonky indentation.

    nuclearsandwich committed
  2. @nuclearsandwich
Showing with 62 additions and 1 deletion.
  1. +1 −0 lib/mustache.rb
  2. +3 −0 lib/mustache/enumerable.rb
  3. +1 −1 lib/mustache/generator.rb
  4. +57 −0 test/mustache_test.rb
View
1 lib/mustache.rb
@@ -1,3 +1,4 @@
+require 'mustache/enumerable'
require 'mustache/template'
require 'mustache/context'
require 'mustache/settings'
View
3 lib/mustache/enumerable.rb
@@ -0,0 +1,3 @@
+class Mustache
+ Enumerable = Module.new
+end
View
2 lib/mustache/generator.rb
@@ -116,7 +116,7 @@ def t.tokens(src=@source)
t.render(ctx.dup)
else
# Shortcut when passed non-array
- v = [v] unless v.is_a?(Array) || defined?(Enumerator) && v.is_a?(Enumerator)
+ v = [v] unless v.is_a?(Array) || v.is_a?(Mustache::Enumerable) || defined?(Enumerator) && v.is_a?(Enumerator)
v.map { |h| ctx.push(h); r = #{code}; ctx.pop; r }.join
end
View
57 test/mustache_test.rb
@@ -344,6 +344,63 @@ def test_enumerable_sections_accept_a_string_keyed_hash_as_a_context
assert_equal ' <li>1234</li> ', instance.render
end
+ def test_enumerable_sections_enumerate_mustache_enumerables
+ person = Struct.new(:name, :age)
+ people_array = []
+ people_array << person.new('Juliet', 13)
+ people_array << person.new('Romeo', 16)
+ people = Class.new do
+ include Enumerable
+ include Mustache::Enumerable
+
+ def initialize array
+ @people = array
+ end
+
+ def each *args, &block
+ @people.each *args, &block
+ end
+ end
+
+ view = Mustache.new
+ view[:people] = people.new(people_array)
+ view.template = <<-TEMPLATE
+{{#people}}
+{{name}} is {{age}}
+{{/people}}
+ TEMPLATE
+ assert_equal <<-EXPECTED, view.render
+Juliet is 13
+Romeo is 16
+ EXPECTED
+ end
+
+ def test_enumerable_sections_do_not_enumerate_untagged_enumerables
+ people = Struct.new(:first, :second, :third)
+ person = Struct.new(:name, :age)
+
+ view = Mustache.new
+ view[:people] = people.new(person.new("Mercutio", 17), person.new("Tybalt", 20), person.new("Benvolio", 15))
+ view.template = <<-TEMPLATE
+{{#people}}
+{{#first}}
+{{name}} is {{age}}
+{{/first}}
+{{#second}}
+{{name}} is {{age}}
+{{/second}}
+{{#third}}
+{{name}} is {{age}}
+{{/third}}
+{{/people}}
+ TEMPLATE
+ assert_equal <<-EXPECTED, view.render
+Mercutio is 17
+Tybalt is 20
+Benvolio is 15
+ EXPECTED
+ end
+
def test_not_found_in_context_renders_empty_string
instance = Mustache.new
instance.template = '{{#list}} <li>{{item}}</li> {{/list}}'
Something went wrong with that request. Please try again.