block_helpers 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown CHANGED
@@ -11,6 +11,18 @@ Rails already has a great solution for forms with form-builders, using helpers w
11
11
 
12
12
  This small gem generates helpers similar to the form-builders, but for the general case.
13
13
 
14
+ Installation
15
+ ============
16
+
17
+ To use in Rails, add to your `environment.rb`:
18
+
19
+ config.gem "block_helpers", :source => "http://gemcutter.org"
20
+
21
+ for Merb, in `init.rb`:
22
+
23
+ dependency "block_helpers"
24
+
25
+
14
26
  Example usage
15
27
  =============
16
28
  Please note that these examples are very contrived just for brevity! These block helpers are much more useful than just printing 'Hi there Marmaduke!'
@@ -161,16 +173,58 @@ This generates:
161
173
 
162
174
  Of course, you could use `display` for more than just surrounding markup.
163
175
 
164
- Installation
165
- ============
176
+ Nesting
177
+ =======
178
+ You can even nest block helpers:
166
179
 
167
- To use in Rails, add to your `environment.rb`:
180
+ module MyHelper
168
181
 
169
- config.gem "block_helpers", :lib => "block_helpers", :source => "http://gemcutter.org"
182
+ class Nav < BlockHelpers::Base
170
183
 
171
- for Merb, in `init.rb`:
184
+ #...code....
172
185
 
173
- dependency "block_helpers"
186
+ class SubNav < BlockHelpers::Base
187
+
188
+ #...code...
189
+
190
+ end
191
+
192
+ end
193
+
194
+ end
195
+
196
+ In the view:
197
+
198
+ <% nav do |h| %>
199
+ ...
200
+ <% h.sub_nav do %>
201
+ ...
202
+ <% end %>
203
+ ...
204
+ <% end %>
205
+
206
+ However... I'd be careful not to abuse this, as the code could end up more confusing than it needs be.
207
+ Nested block helpers can access the parent block helper by using the `parent` method.
208
+
209
+ Testing
210
+ =======
211
+ I'm not too sure about other testing frameworks, but with rspec-rails you can use 'eval_erb', e.g.
212
+
213
+ eval_erb(%(
214
+ <% my_block_helper do |h| %>
215
+ <h2>Hello</h2>
216
+ <%= h.write_blah %>
217
+ <% end %>
218
+ )).should match_html("<h2>Hello</h2> blah blah blah ")
219
+
220
+ In the above I've used the following simple matcher `match_html`:
221
+
222
+ def match_html(html)
223
+ # Match two strings, but don't care about whitespace
224
+ simple_matcher("should match #{html}"){|given| given.strip.gsub(/\s+/,' ').gsub('> <','><') == html.strip.gsub(/\s+/,' ').gsub('> <','><') }
225
+ end
226
+
227
+ Obviously you test however you want but I've included the above in case it's useful.
174
228
 
175
229
  Compatibility
176
230
  =============
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{block_helpers}
8
- s.version = "0.3.0"
8
+ s.version = "0.3.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mark Evans"]
12
- s.date = %q{2009-10-12}
12
+ s.date = %q{2009-11-06}
13
13
  s.email = %q{mark@new-bamboo.co.uk}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
data/lib/block_helpers.rb CHANGED
@@ -4,37 +4,59 @@ module BlockHelpers
4
4
 
5
5
  class Base
6
6
 
7
- def self.inherited(klass)
8
- # Define the helper method
9
- # e.g. for a class:
10
- # class HelloHelper < BlockHelpers::Base
11
- # #.....
12
- # end
13
- #
14
- # then we define a helper method 'hello_helper'
15
- #
16
- method_name = klass.name.split('::').last.underscore
17
- klass.parent.class_eval %(
18
- def #{method_name}(*args, &block)
19
- renderer = #{klass.name}.new(*args)
20
- top_level_helper = if self.is_a?(BlockHelpers::Base)
21
- self.helper
22
- else
23
- self
24
- end
25
- renderer.send(:helper=, top_level_helper)
26
- body = block ? capture(renderer, &block) : nil
27
- processed_body = renderer.display(body)
28
- if processed_body
29
- if top_level_helper.method(:concat).arity == 2
30
- concat processed_body, binding
7
+ class << self
8
+
9
+ def inherited(klass)
10
+ # Define the helper method
11
+ # e.g. for a class:
12
+ # class HelloHelper < BlockHelpers::Base
13
+ # #.....
14
+ # end
15
+ #
16
+ # then we define a helper method 'hello_helper'
17
+ #
18
+ method_name = klass.name.split('::').last.underscore
19
+ klass.parent.class_eval %(
20
+ def #{method_name}(*args, &block)
21
+
22
+ # Get the current helper object which has all the normal helper methods
23
+ if self.is_a?(BlockHelpers::Base)
24
+ top_level_helper = self.helper
25
+ parent_block_helper = self
31
26
  else
32
- concat processed_body
27
+ top_level_helper = self
28
+ parent_block_helper = nil
29
+ end
30
+
31
+ # We need to save the current helper and parent block helper in the class so that
32
+ # it's visible to the renderer's 'initialize' method...
33
+ #{klass.name}.current_helper = top_level_helper
34
+ #{klass.name}.current_parent_block_helper = parent_block_helper
35
+ renderer = #{klass.name}.new(*args)
36
+ # ...then set them anyway on the renderer so that renderer methods can use it
37
+ renderer.send(:helper=, top_level_helper)
38
+ renderer.send(:parent=, parent_block_helper)
39
+
40
+ body = block ? capture(renderer, &block) : nil
41
+ processed_body = renderer.display(body)
42
+ if processed_body
43
+
44
+ # If concat is the old rails/merb version with 2 args...
45
+ if top_level_helper.method(:concat).arity == 2
46
+ concat processed_body, binding
47
+ # ...otherwise call with one arg
48
+ else
49
+ concat processed_body
50
+ end
51
+
33
52
  end
53
+ renderer
34
54
  end
35
- renderer
36
- end
37
- )
55
+ )
56
+ end
57
+
58
+ attr_accessor :current_helper, :current_parent_block_helper
59
+
38
60
  end
39
61
 
40
62
  def display(body)
@@ -47,7 +69,16 @@ module BlockHelpers
47
69
 
48
70
  protected
49
71
 
50
- attr_accessor :helper
72
+ attr_writer :helper, :parent
73
+
74
+ # For nested block helpers
75
+ def parent
76
+ @parent ||= self.class .current_parent_block_helper
77
+ end
78
+
79
+ def helper
80
+ @helper ||= self.class.current_helper
81
+ end
51
82
 
52
83
  def method_missing(method, *args, &block)
53
84
  if helper.respond_to?(method)
@@ -95,6 +95,21 @@ describe TestHelperModule do
95
95
  <% end %>
96
96
  )).should match_html("<div>jelly</div>")
97
97
  end
98
+ it "should give the yielded renderer access to normal actionview helper methods even in initialize" do
99
+ module TestHelperModule
100
+ class JokeHelper < BlockHelpers::Base
101
+ def initialize
102
+ @joke = truncate("What's the different between half a duck?", :length => 6)
103
+ end
104
+ attr_reader :joke
105
+ end
106
+ end
107
+ eval_erb(%(
108
+ <% joke_helper do |r| %>
109
+ <%= r.joke %>
110
+ <% end %>
111
+ )).should match_html("Wha...")
112
+ end
98
113
  it "should give the yielded renderer access to other methods via 'helper'" do
99
114
  eval_erb(%(
100
115
  <% test_helper do |r| %>
@@ -287,7 +302,7 @@ describe TestHelperModule do
287
302
  class OuterHelper < BlockHelpers::Base
288
303
 
289
304
  def egg
290
- 'bad egg'
305
+ 'bad egg ' + parent.inspect
291
306
  end
292
307
 
293
308
  def display(body)
@@ -295,8 +310,13 @@ describe TestHelperModule do
295
310
  end
296
311
 
297
312
  class InnerHelper < BlockHelpers::Base
313
+
314
+ def initialize
315
+ @egg = parent.egg
316
+ end
317
+
298
318
  def egg
299
- 'EGG'
319
+ @egg + ' ' + parent.egg.upcase
300
320
  end
301
321
  def display(body)
302
322
  "Inner #{body}"
@@ -310,7 +330,7 @@ describe TestHelperModule do
310
330
  <%= i.egg %>
311
331
  <% end %>
312
332
  <% end %>
313
- )).should match_html("Outer Inner EGG")
333
+ )).should match_html("Outer Inner bad egg nil BAD EGG NIL")
314
334
  end
315
335
  end
316
336
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: block_helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Evans
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-12 00:00:00 +01:00
12
+ date: 2009-11-06 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency