Permalink
Browse files

Added 'parent' method for nested block helpers, and added README for …

…nested helpers
  • Loading branch information...
1 parent b7f74d6 commit d21173c4e1510f1d4054a52ffe734346f2018015 Mark Evans committed Nov 6, 2009
Showing with 58 additions and 11 deletions.
  1. +33 −0 README.markdown
  2. +17 −8 lib/block_helpers.rb
  3. +8 −3 spec/helpers/block_helpers_spec.rb
View
@@ -173,6 +173,39 @@ This generates:
Of course, you could use `display` for more than just surrounding markup.
+Nesting
+=======
+You can even nest block helpers:
+
+ module MyHelper
+
+ class Nav < BlockHelpers::Base
+
+ #...code....
+
+ class SubNav < BlockHelpers::Base
+
+ #...code...
+
+ end
+
+ end
+
+ end
+
+In the view:
+
+ <% nav do |h| %>
+ ...
+ <% h.sub_nav do %>
+ ...
+ <% end %>
+ ...
+ <% end %>
+
+However... I'd be careful not to abuse this, as the code could end up more confusing than it needs be.
+Nested block helpers can access the parent block helper by using the `parent` method.
+
Testing
=======
I'm not too sure about other testing frameworks, but with rspec-rails you can use 'eval_erb', e.g.
View
@@ -20,19 +20,23 @@ def inherited(klass)
def #{method_name}(*args, &block)
# Get the current helper object which has all the normal helper methods
- top_level_helper = if self.is_a?(BlockHelpers::Base)
- self.helper
+ if self.is_a?(BlockHelpers::Base)
+ top_level_helper = self.helper
+ parent_block_helper = self
else
- self
+ top_level_helper = self
+ parent_block_helper = nil
end
- # We need to save the current helper in the class so that
+ # We need to save the current helper and parent block helper in the class so that
# it's visible to the renderer's 'initialize' method...
#{klass.name}.current_helper = top_level_helper
+ #{klass.name}.current_parent_block_helper = parent_block_helper
renderer = #{klass.name}.new(*args)
- # ...then set it anyway on the renderer so that renderer methods can use it
+ # ...then set them anyway on the renderer so that renderer methods can use it
renderer.send(:helper=, top_level_helper)
-
+ renderer.send(:parent=, parent_block_helper)
+
body = block ? capture(renderer, &block) : nil
processed_body = renderer.display(body)
if processed_body
@@ -51,7 +55,7 @@ def #{method_name}(*args, &block)
)
end
- attr_accessor :current_helper
+ attr_accessor :current_helper, :current_parent_block_helper
end
@@ -65,7 +69,12 @@ def respond_to?(method)
protected
- attr_writer :helper
+ attr_writer :helper, :parent
+
+ # For nested block helpers
+ def parent
+ @parent ||= self.class .current_parent_block_helper
+ end
def helper
@helper ||= self.class.current_helper
@@ -302,16 +302,21 @@ module TestHelperModule
class OuterHelper < BlockHelpers::Base
def egg
- 'bad egg'
+ 'bad egg ' + parent.inspect
end
def display(body)
"Outer #{body}"
end
class InnerHelper < BlockHelpers::Base
+
+ def initialize
+ @egg = parent.egg
+ end
+
def egg
- 'EGG'
+ @egg + ' ' + parent.egg.upcase
end
def display(body)
"Inner #{body}"
@@ -325,7 +330,7 @@ def display(body)
<%= i.egg %>
<% end %>
<% end %>
- )).should match_html("Outer Inner EGG")
+ )).should match_html("Outer Inner bad egg nil BAD EGG NIL")
end
end

0 comments on commit d21173c

Please sign in to comment.