express_templates 0.2.7 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/core_extensions/proc.rb +72 -20
  3. data/lib/express_templates/compiler.rb +9 -1
  4. data/lib/express_templates/components/base.rb +1 -1
  5. data/lib/express_templates/components/capabilities/building.rb +8 -0
  6. data/lib/express_templates/components/capabilities/conditionality.rb +8 -6
  7. data/lib/express_templates/components/capabilities/configurable.rb +3 -4
  8. data/lib/express_templates/components/capabilities/iterating.rb +18 -23
  9. data/lib/express_templates/components/capabilities/parenting.rb +4 -18
  10. data/lib/express_templates/components/capabilities/rendering.rb +2 -65
  11. data/lib/express_templates/components/capabilities/templating.rb +24 -22
  12. data/lib/express_templates/components/capabilities/wrapping.rb +23 -39
  13. data/lib/express_templates/components/column.rb +1 -1
  14. data/lib/express_templates/components/for_each.rb +28 -0
  15. data/lib/express_templates/components/form_for.rb +19 -0
  16. data/lib/express_templates/components/form_rails_support.rb +1 -1
  17. data/lib/express_templates/components/null_wrap.rb +9 -0
  18. data/lib/express_templates/components/row.rb +1 -1
  19. data/lib/express_templates/components/table_for.rb +119 -0
  20. data/lib/express_templates/components/tree_for.rb +41 -0
  21. data/lib/express_templates/components/unless_block.rb +40 -0
  22. data/lib/express_templates/components.rb +4 -0
  23. data/lib/express_templates/expander.rb +15 -4
  24. data/lib/express_templates/indenter.rb +8 -5
  25. data/lib/express_templates/markup/tag.rb +62 -30
  26. data/lib/express_templates/markup/wrapper.rb +1 -1
  27. data/lib/express_templates/version.rb +1 -1
  28. data/test/components/base_test.rb +5 -38
  29. data/test/components/conditionality_test.rb +1 -1
  30. data/test/components/configurable_test.rb +2 -2
  31. data/test/components/container_test.rb +1 -1
  32. data/test/components/iterating_test.rb +30 -9
  33. data/test/components/table_for_test.rb +116 -0
  34. data/test/core_extensions/proc_test.rb +35 -5
  35. data/test/dummy/log/test.log +645 -0
  36. data/test/fixtures/{a_big_page.html → a_big_page2.html} +0 -0
  37. data/test/indenter_test.rb +6 -4
  38. data/test/markup/tag_test.rb +15 -2
  39. data/test/performance_test.rb +1 -1
  40. data/test/test_helper.rb +2 -0
  41. metadata +26 -3
@@ -0,0 +1,119 @@
1
+ module ExpressTemplates
2
+ module Components
3
+ # Create an html table from a collection of data.
4
+ #
5
+ # Typically this will be a collection of models
6
+ # of the same type. Each member of the collection must
7
+ # respond to the column names provided.
8
+ #
9
+ # Example:
10
+ #
11
+ # ```ruby
12
+ # table_for(:people) do |t|
13
+ # t.column :name
14
+ # t.column :email
15
+ # t.column :phone
16
+ # end
17
+ # ```
18
+ #
19
+ # This assumes that a @people variable will exist in the
20
+ # view and that it will be a collection whose members respond to
21
+ # :name, :email, and :phone
22
+ #
23
+ # This will result in markup like the following:
24
+ #
25
+ # <table id="people">
26
+ # <thead>
27
+ # <tr>
28
+ # <th class="name">Name</th>
29
+ # <th class="email">Email</th>
30
+ # <th class="phone">Phone</th>
31
+ # </tr>
32
+ # </thead>
33
+ # <tbody>
34
+ # <tr id="person-1">
35
+ # <td class="name">Steven Talcott Smith</td>
36
+ # <td class="email">steve@aelogica.com</td>
37
+ # <td class="phone">415-555-1212</td>
38
+ # </tr>
39
+ # </tbody>
40
+ # </table>
41
+ #
42
+ class TableFor < Base
43
+ include Capabilities::Configurable
44
+ include Capabilities::Building
45
+
46
+ def initialize(*args)
47
+ super(*args)
48
+ _process_args!(args) # from Configurable
49
+ yield(self) if block_given?
50
+ end
51
+
52
+ attr :columns
53
+
54
+ def column(name, options = {})
55
+ @columns ||= []
56
+ @columns << Column.new(name, options)
57
+ end
58
+
59
+ emits -> {
60
+ table(my[:id]) {
61
+ thead {
62
+ tr {
63
+ columns.each do |column|
64
+ th.send(column.name) {
65
+ column.title
66
+ }
67
+ end
68
+ }
69
+ }
70
+ tbody {
71
+ for_each(my[:id]) {
72
+
73
+ tr(id: -> {"item-#{item.id}"},
74
+ class: my[:id].to_s.singularize) {
75
+
76
+ columns.each do |column|
77
+ td(class: column.name) {
78
+ column.format(:item)
79
+ }
80
+ end
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ def wrap_for_stack_trace(body)
88
+ "ExpressTemplates::Components::TableFor.render_in(self) {\n#{body}\n}"
89
+ end
90
+
91
+ def compile
92
+ wrap_for_stack_trace(lookup(:markup))
93
+ end
94
+
95
+ class Column
96
+ attr :name, :options
97
+ def initialize(name, options = {})
98
+ @name = name
99
+ @options = options
100
+ @formatter = options[:formatter]
101
+ end
102
+
103
+ def format(item_name)
104
+ if @formatter.nil?
105
+ "\#\{#{item_name}.#{name}\}"
106
+ elsif @formatter.kind_of?(Proc)
107
+ "\#\{(#{@formatter.source}).call(#{item_name}.#{name})\}"
108
+ end
109
+ end
110
+
111
+ def title
112
+ @name.to_s.try(:titleize)
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,41 @@
1
+ module ExpressTemplates
2
+ module Components
3
+ #
4
+ # Create an html <tt>table</tt> or <tt>ol</tt> (ordered list) for
5
+ # a model object representing a tree of similar objects.
6
+ #
7
+ # The objects must respond to <tt>:children</tt>.
8
+ #
9
+ # The block is passed a NodeBuilder which may accept field names.
10
+ #
11
+ # Example:
12
+ #
13
+ # ```ruby
14
+ # tree_for(:roles) do |role|
15
+ # role.name
16
+ # end
17
+ # ```
18
+ #
19
+ # If the view has an @roles variable with a Role having children,
20
+ # this will turn into markup such as the following:
21
+ #
22
+ # <ul id="roles" class="roles tree">
23
+ # <li>SuperAdmin
24
+ # <ul>
25
+ # <li>Admin</li>
26
+ # <ul>
27
+ # <li>Publisher</li>
28
+ # <ul>
29
+ # <li>Author</li>
30
+ # </ul>
31
+ # <li>Auditor</li>
32
+ # </ol>
33
+ # </li>
34
+ # </ol>
35
+ # </li>
36
+ # </ol>
37
+ #
38
+ class TreeFor < Container
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,40 @@
1
+ module ExpressTemplates
2
+ module Components
3
+ class UnlessBlock < Components::Container
4
+
5
+ attr :conditional
6
+
7
+ def initialize(*args)
8
+ @conditional = args.shift
9
+ @alt = args.shift[:alt] if args.first.kind_of?(Hash)
10
+ parent = args.shift
11
+ if @conditional.kind_of?(Symbol)
12
+ @conditional = @conditional.to_s
13
+ elsif @conditional.kind_of?(Proc)
14
+ @conditional = "(#{@conditional.source}.call)"
15
+ elsif iterator.kind_of?(String)
16
+ @conditional = "(#{@conditional}.call)"
17
+ else
18
+ raise "UnlessBlock unknown conditional: #{@conditional.inspect}"
19
+ end
20
+
21
+ if @alt.kind_of?(Proc)
22
+ @alt = _compile_fragment @alt
23
+ elsif @alt.nil?
24
+ @alt = "''"
25
+ end
26
+ end
27
+
28
+ def compile
29
+ s = unless @alt
30
+ %Q((unless #{@conditional}#{compile_children}\nend))
31
+ else
32
+ %Q((unless #{@conditional}#{compile_children}\nelse #{@alt}\nend))
33
+ end
34
+ puts s if ENV['DEBUG'].eql?('true')
35
+ s
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -6,7 +6,11 @@ end
6
6
  require 'express_templates/expander'
7
7
  require 'express_templates/components/base'
8
8
  require 'express_templates/components/container'
9
+ require 'express_templates/components/null_wrap'
10
+ require 'express_templates/components/for_each'
11
+ require 'express_templates/components/unless_block'
9
12
  require 'express_templates/components/row'
10
13
  require 'express_templates/components/column'
11
14
  require 'express_templates/components/form_rails_support'
12
15
  require 'express_templates/components/content_for'
16
+ require 'express_templates/components/table_for'
@@ -6,11 +6,16 @@ module ExpressTemplates
6
6
 
7
7
  attr_accessor :stack, :handlers, :locals
8
8
 
9
- def initialize(template, handlers = {}, locals = {})
9
+ def initialize(*args)
10
+ initialize_expander(*args)
11
+ end
12
+
13
+ def initialize_expander(template, handlers = {}, locals = {})
10
14
  @template = template
11
15
  @stack = Stack.new
12
16
  @handlers = handlers
13
17
  @locals = locals
18
+ self
14
19
  end
15
20
 
16
21
  def expand(source=nil, &block)
@@ -47,8 +52,14 @@ module ExpressTemplates
47
52
  def self.register_macros_for(*components)
48
53
  components.each do |component|
49
54
  define_method(component.macro_name.to_sym) do |*args, &block|
50
- new_component = component.new(*(args.push(self)))
51
- process_children!(new_component, &block) unless block.nil?
55
+ new_component = nil
56
+ # this is a code smell here.
57
+ if component.ancestors.include?(Components::Capabilities::Building)
58
+ new_component = component.new(*(args.push(self)), &block)
59
+ else
60
+ new_component = component.new(*(args.push(self)))
61
+ process_children!(new_component, &block) unless block.nil?
62
+ end
52
63
  stack << new_component
53
64
  end
54
65
  end
@@ -68,7 +79,7 @@ module ExpressTemplates
68
79
  return locals[name] if locals.keys.include?(name)
69
80
 
70
81
  if handlers.keys.include?(name)
71
- stack << handlers[name].send(name, *args)
82
+ stack << handlers[name].send(name, *args, &block)
72
83
  else
73
84
  stack << ExpressTemplates::Markup::Wrapper.new(name.to_s, *args, &block)
74
85
  end
@@ -23,10 +23,13 @@ module ExpressTemplates
23
23
  indent = WHITESPACE * current_indenters[name]
24
24
  yield indent, "\n#{indent}"
25
25
  ensure
26
- current_indenters[name] -= 1
27
- # if we have long-lived threads for some reason
28
- # we want to clean up after ourselves
29
- current_indenters.delete(name) if current_indenters[name].eql?(0)
26
+ if current_indenters[name].eql?(-1)
27
+ # if we have long-lived threads for some reason
28
+ # we want to clean up after ourselves
29
+ current_indenters.delete(name)
30
+ else
31
+ current_indenters[name] -= 1
32
+ end
30
33
  end
31
34
  else
32
35
  return WHITESPACE * current_indenters[name]
@@ -36,7 +39,7 @@ module ExpressTemplates
36
39
  private
37
40
  # For thread safety, scope indentation to the current thread
38
41
  def self.current_indenters
39
- Thread.current[:indenters] ||= Hash.new {|hsh, key| hsh[key] = 0 }
42
+ Thread.current[:indenters] ||= Hash.new {|hsh, key| hsh[key] = -1 }
40
43
  end
41
44
 
42
45
  end
@@ -22,6 +22,8 @@ module ExpressTemplates
22
22
  case
23
23
  when name.to_sym.eql?(:data) && value.kind_of?(Hash)
24
24
  value.each_pair.map {|k,v| %Q(data-#{k}=\\"#{v}\\") }.join(" ")
25
+ when value.kind_of?(Proc)
26
+ %Q(#{name}=\\"\#{(#{value.source}).call}\\")
25
27
  when code = value.to_s.match(/^\{\{(.*)\}\}$/).try(:[], 1)
26
28
  %Q(#{name}=\\"\#{#{code}}\\")
27
29
  else
@@ -66,56 +68,86 @@ module ExpressTemplates
66
68
  end
67
69
 
68
70
  def compile
69
- ruby_fragments = @children.map do |child|
70
- if child.respond_to?(:compile)
71
- child.compile
72
- else
73
- if code = child.to_s.match(/\{\{(.*)\}\}/).try(:[], 1)
74
- %Q("\#\{#{code}\}")
71
+ ExpressTemplates::Indenter.for(:markup) do |whitespace|
72
+ ruby_fragments = @children.map do |child|
73
+ if child.respond_to?(:compile)
74
+ child.compile
75
75
  else
76
- %Q("#{child}")
76
+ if code = child.to_s.match(/\{\{(.*)\}\}/).try(:[], 1)
77
+ %Q("\#\{#{code}\}")
78
+ else
79
+ %Q("#{child}")
80
+ end
77
81
  end
78
82
  end
79
- end
80
- unless ruby_fragments.empty?
81
- _wrap_with_tags(ruby_fragments)
82
- else
83
- if should_not_abbreviate?
84
- _wrap_with_tags(ruby_fragments)
85
- elsif transform_close_tag?
86
- %Q("#{start_tag.gsub(/>$/, ' />')}")
83
+ unless ruby_fragments.empty?
84
+ _wrap_with_tags(ruby_fragments, whitespace)
87
85
  else
88
- %Q("#{start_tag}")
86
+ if should_not_abbreviate?
87
+ _wrap_with_tags(ruby_fragments, whitespace)
88
+ elsif transform_close_tag?
89
+ %Q("#{start_tag.gsub(/>$/, ' />')}")
90
+ else
91
+ %Q("#{start_tag}")
92
+ end
89
93
  end
90
94
  end
91
95
  end
92
96
 
93
- def to_template(depth = 0)
94
- template_fragments = @children.map do |child|
95
- if child.respond_to?(:to_template)
96
- child.to_template(depth+1)
97
- else
98
- child
97
+ def to_template
98
+ # ExpressTemplates::Indenter.for(:template) do
99
+ template_fragments = @children.map do |child|
100
+ if child.respond_to?(:to_template)
101
+ child.to_template
102
+ else
103
+ child
104
+ end
99
105
  end
106
+ macro_name + _blockify(template_fragments.join("\n"))
107
+ # end
108
+ end
109
+
110
+ def self.formatted
111
+ old_setting = Thread.current[:formatted]
112
+ begin
113
+ Thread.current[:formatted] = true
114
+ yield if block_given?
115
+ ensure
116
+ Thread.current[:formatted] = old_setting
100
117
  end
101
- indent = INDENT*(depth+1)
102
- macro_name + _blockify(template_fragments.join("\n#{indent}"), depth)
103
118
  end
104
119
 
105
120
  private
106
121
 
107
- def _wrap_with_tags(ruby_fragments)
108
- ruby_fragments.unshift %Q("#{start_tag}")
109
- ruby_fragments.push %Q("#{close_tag}")
122
+ def _wrap_with_tags(ruby_fragments, whitespace)
123
+ opening, closing = nil, nil
124
+ if !ENV['ET_NO_INDENT_MARKUP'].eql?('true') || #TODO: change to setting
125
+ Thread.current[:formatted]
126
+ child_code = ruby_fragments.join
127
+ should_format = ruby_fragments.size > 1 ||
128
+ (child_code.size > 40 && !child_code.match(/^"\#\{.*\}"$/)) ||
129
+ child_code.match(/\n/)
130
+
131
+ nl = should_format ? "\n" : nil
132
+ nl_after_start = !ruby_fragments.first.try(:match, /^"\n/) ? nl : nil
133
+ # binding.pry
134
+ nl_before_end = !ruby_fragments.last.try(:match, /\n"$/) ? nl : nil
135
+ opening = %Q("\n#{whitespace}#{start_tag}#{nl_after_start}")
136
+ closing = %Q("#{nl_before_end}#{should_format && whitespace}#{close_tag}#{nl}")
137
+ else
138
+ opening = %Q("#{start_tag}")
139
+ closing = %Q("#{close_tag}")
140
+ end
141
+ ruby_fragments.unshift opening
142
+ ruby_fragments.push closing
110
143
  ruby_fragments.reject {|frag| frag.empty? }.join("+")
111
144
  end
112
145
 
113
146
  def _indent(code)
114
- code.split("\n").map {|line| INDENT + line }.join("\n")
147
+ code.split("\n").map {|line| ExpressTemplates::Indenter::WHITESPACE + line }.join("\n")
115
148
  end
116
149
 
117
- def _blockify(code, depth)
118
- indent = INDENT*depth
150
+ def _blockify(code)
119
151
  code.empty? ? code : " {\n#{_indent(code)}\n}\n"
120
152
  end
121
153
 
@@ -67,7 +67,7 @@ module ExpressTemplates
67
67
  when value.is_a?(Hash)
68
68
  s << value.inspect
69
69
  when value.is_a?(Proc)
70
- s << "(-> #{value.source}).call"
70
+ s << "(#{value.source}).call"
71
71
  else
72
72
  s << value.inspect # immediate values 1, 2.0, true etc
73
73
  end
@@ -1,3 +1,3 @@
1
1
  module ExpressTemplates
2
- VERSION = "0.2.7"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -3,55 +3,32 @@ require 'test_helper'
3
3
  class BaseTest < ActiveSupport::TestCase
4
4
 
5
5
  class NoLogic < ExpressTemplates::Components::Base
6
- has_markup {
6
+ has_markup -> {
7
7
  h1 { span "Some stuff" }
8
8
  }
9
9
  end
10
10
 
11
11
  test ".has_markup makes compile return the block passed through express compiled" do
12
- assert_equal %Q("<h1>"+"<span>"+"Some stuff"+"</span>"+"</h1>"), NoLogic.new.compile
12
+ assert_equal %Q("<h1><span>Some stuff</span></h1>"), NoLogic.new.compile
13
13
  end
14
14
 
15
15
  test "components register themselves as macros" do
16
16
  assert ExpressTemplates::Expander.instance_methods.include?(:no_logic)
17
17
  end
18
18
 
19
- test ".render accepts a fragment name" do
20
- assert_equal '<h1><span>Some stuff</span></h1>', NoLogic.render(self, :markup)
21
- end
22
-
23
-
24
- class SomeLogic < ECB
25
- emits markup: -> {
26
- span { foo }
27
- }
28
-
29
- using_logic { |component|
30
- @foo.map do |foo|
31
- eval(component[:markup])
32
- end.join
33
- }
34
- end
35
-
36
19
  class Context
37
20
  def initialize ; @foo = ['bar', 'baz'] ; end
38
21
  end
39
22
 
40
- test ".using_logic controls the markup generation" do
41
- compiled = SomeLogic.new.compile
42
- assert_equal 'BaseTest::SomeLogic.render(self)', compiled
43
- assert_equal '<span>bar</span><span>baz</span>', Context.new.instance_eval(compiled)
44
- end
45
-
46
23
  test "fragments and has_markup are synonyms for emits" do
47
- assert_equal SomeLogic.method(:emits), SomeLogic.method(:fragments)
48
- assert_equal SomeLogic.method(:emits), SomeLogic.method(:has_markup)
24
+ assert_equal NoLogic.method(:emits), NoLogic.method(:fragments)
25
+ assert_equal NoLogic.method(:emits), NoLogic.method(:has_markup)
49
26
  end
50
27
 
51
28
  class Helpers < ECB
52
29
  helper :title_helper, &-> { @foo.first }
53
30
 
54
- emits {
31
+ emits -> {
55
32
  h1 {
56
33
  title_helper
57
34
  }
@@ -64,14 +41,4 @@ class BaseTest < ActiveSupport::TestCase
64
41
  assert_equal "<h1>bar</h1>", Context.new.instance_eval(compiled)
65
42
  end
66
43
 
67
- class NullComponent < ECB
68
- using_logic {
69
- nil
70
- }
71
- end
72
-
73
- test "render should not return a nil" do
74
- compiled = NullComponent.new.compile
75
- assert_equal "", Context.new.instance_eval(compiled)
76
- end
77
44
  end
@@ -17,7 +17,7 @@ class ConditionalityTest < ActiveSupport::TestCase
17
17
  class ConditionalRenderer < ExpressTemplates::Components::Base
18
18
  include ExpressTemplates::Components::Capabilities::Conditionality
19
19
 
20
- emits {
20
+ emits -> {
21
21
  h1 "{{@title}}"
22
22
  }
23
23
 
@@ -6,7 +6,7 @@ class ConfigurableTest < ActiveSupport::TestCase
6
6
 
7
7
  class ConfigurableComponent < ETC::Base
8
8
  include ETC::Capabilities::Configurable
9
- emits {
9
+ emits -> {
10
10
  div.bar(my[:id])
11
11
  }
12
12
  end
@@ -27,7 +27,7 @@ class ConfigurableTest < ActiveSupport::TestCase
27
27
  # make sure a helper can take arguments
28
28
  helper(:name) {|name| name.to_s }
29
29
 
30
- emits {
30
+ emits -> {
31
31
  div(my[:id]) {
32
32
  h1 { name(my[:id]) }
33
33
  _yield
@@ -26,7 +26,7 @@ class ContainerTest < ActiveSupport::TestCase
26
26
  end
27
27
 
28
28
  class TestContainer < ETC::Container
29
- emits { p { _yield } }
29
+ emits -> { p { _yield } }
30
30
  end
31
31
 
32
32
  test "Container#compile calls #compile on its children" do
@@ -3,26 +3,47 @@ require 'test_helper'
3
3
  class IteratingTest < ActiveSupport::TestCase
4
4
 
5
5
  class Context
6
- def initialize ; @foo = ['bar', 'baz'] ; @empty = [] ; end
6
+ def initialize ; @things = ['bar', 'baz'] ; @empty = [] ; end
7
7
  end
8
8
 
9
9
  class ForEachLogic < ECB
10
10
  emits -> {
11
- span { foo }
11
+ for_each(:@things) {
12
+ span { thing }
13
+ }
12
14
  }
15
+ end
13
16
 
14
- for_each(:@foo)
17
+ test "#for_each expands to view logic" do
18
+ compiled = ForEachLogic.new.compile
19
+ assert_equal %q((@things.each_with_index.map do |thing, thing_index|
20
+ "<span>#{thing}</span>"
21
+ end).join), compiled
15
22
  end
16
23
 
17
- test ".for_each iterates markup for each value" do
24
+ test "#for_each iterates markup for each value" do
18
25
  compiled = ForEachLogic.new.compile
19
26
  assert_equal '<span>bar</span><span>baz</span>', Context.new.instance_eval(compiled)
20
27
  end
21
28
 
29
+ class ForEachDeclarativeForm < ECB
30
+ emits -> {
31
+ span { thing }
32
+ }
33
+
34
+ for_each(:@things)
35
+ end
36
+
37
+ test ".for_each offers declarative form" do
38
+ compiled = ForEachLogic.new.compile
39
+ assert_equal '<span>bar</span><span>baz</span>', Context.new.instance_eval(compiled)
40
+ end
41
+
42
+
22
43
  class MultiFragments < ECB
23
44
 
24
45
  fragments item: -> {
25
- li { foo }
46
+ li { thing }
26
47
  },
27
48
 
28
49
  wrapper: -> {
@@ -31,7 +52,7 @@ class IteratingTest < ActiveSupport::TestCase
31
52
  }
32
53
  }
33
54
 
34
- for_each -> { @foo }, as: 'foo', emit: :item
55
+ for_each -> { @things }, as: 'thing', emit: :item
35
56
 
36
57
  wrap_with :wrapper
37
58
 
@@ -45,7 +66,7 @@ class IteratingTest < ActiveSupport::TestCase
45
66
  class EmptyState < ECB
46
67
 
47
68
  fragments item: -> {
48
- li { foo }
69
+ li { thing }
49
70
  },
50
71
 
51
72
  wrapper: -> {
@@ -57,7 +78,7 @@ class IteratingTest < ActiveSupport::TestCase
57
78
  p "Nothing here"
58
79
  }
59
80
 
60
- for_each -> { @empty }, as: 'foo', emit: :item, empty: :empty_state
81
+ for_each -> { @empty }, as: 'thing', emit: :item, empty: :empty_state
61
82
 
62
83
  wrap_with :wrapper, dont_wrap_if: -> { @empty.empty? }
63
84
 
@@ -69,7 +90,7 @@ class IteratingTest < ActiveSupport::TestCase
69
90
  end
70
91
 
71
92
  class EmptyEmptyState < ECB
72
- emits {
93
+ emits -> {
73
94
  whatever
74
95
  }
75
96