block_helpers 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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