ruhl 0.9.7 → 0.10.0

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 CHANGED
@@ -2,392 +2,7 @@ RuHL (Ruby Hypertext Language)
2
2
 
3
3
  **gem available on gemcutter: http://gemcutter.org/gems/ruhl
4
4
 
5
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6
- :: What? ::
7
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
+ Documentation has been moved to:
8
6
 
9
- RuHL parses HTML (using Nokogiri) and by using a data-ruhl attribute, makes
10
- the contents dynamic!
11
-
12
- Let's say you have the following HTML in a file called ('hello_world.ruhl')
13
-
14
- <html>
15
- <body>
16
- <p data-ruhl="say_hello"/>
17
- </body>
18
- </html>
19
-
20
- And you have the following method available to self:
21
-
22
- def say_hello
23
- "Hello World"
24
- end
25
-
26
- If you call
27
-
28
- RuHL::Engine.new(File.read('hello_world.ruhl')).render(self)
29
-
30
- It will return:
31
-
32
- <html>
33
- <body>
34
- <p>Hello World</p>
35
- </body>
36
- </html>
37
-
38
- Notice that it removes the data-ruhl attribute.
39
-
40
-
41
- You can pass an options hash to RuHL:
42
- RuHL::Engine.new(File.read('hello_world.ruhl'), options).render(self)
43
-
44
- Right now, RuHL knows the following options:
45
-
46
- :layout => This is the file name of the layout
47
-
48
- :layout_source => If the framework (like Rails) has already read the file,
49
- pass the contents through so RuHL doesn't have to reread
50
- the file.
51
-
52
- If you don't pass :layout_source, RuHL must be able to
53
- find/read :layout
54
-
55
- :local_object => If you are rendering a show page for @person, pass the
56
- @person object into RuHL. RuHL will first try to call
57
- the methods against the local_object then try the scope.
58
-
59
- For example:
60
- <li data-ruhl="first_name">
61
-
62
- RuHL will first try @person.first_name.
63
-
64
-
65
-
66
- There are some special methods defined by RuHL (examples follow):
67
-
68
- _render_ - This is used in your layout and lets rule know where to inject
69
- the rendered sub content.
70
-
71
- _partial - Path to a partial file. RuHL must be able to find/read this file.
72
-
73
- _if - If the method returns true, processing will continue.
74
- If the method returns a value other than true, the inner_html
75
- of the tag will be set to that value.
76
- If the method returns false or nil, processing will halt and
77
- the tag will not be included on output.
78
-
79
- _unless - If the method returns true, processing will halt and the tag
80
- will not included on output.
81
- If the method returns false, processing will continue.
82
-
83
- _collection - RuHL expects the method reference to return an array of objects.
84
- RuHL will iteratate over the collection and render the contents
85
- of the tag agains the collection item. (example below)
86
-
87
- _use - The object returned is used within the scope of the tag.
88
-
89
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90
- :: Rails ::
91
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92
-
93
- In your config/environment.rb :
94
-
95
- config.gem 'ruhl', :lib => 'ruhl/rails'
96
-
97
- Your filenames should end in .ruhl ('show.html.ruhl')
98
-
99
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100
- :: Sinatra ::
101
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102
-
103
- require 'ruhl/sinatra'
104
-
105
- You can then do:
106
-
107
- get '/' do
108
- ruhl(:index, :layout => path_to_layout)
109
- end
110
-
111
- *******************************************************************************
112
- *
113
- * EXAMPLES
114
- *
115
- *******************************************************************************
116
-
117
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118
- :: Replacing attribute values ::
119
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
-
121
- <meta data-ruhl="content: meta_description" content='This is a description template'
122
- id='metaDescription' name='description' />
123
-
124
- content: meta_description is telling the parser to replace attribute 'content'
125
- with results from meta_description method.
126
-
127
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128
- :: Don't use iterators in views ::
129
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130
-
131
- <table id="aab">
132
- <tr data-ruhl="_collection: user_list">
133
- <td data-ruhl="name">John Doe</td>
134
- <td data-ruhl="email">john@doe.com</td>
135
- </tr>
136
- </table>
137
-
138
- The above will call the :user_list method and iterate over the results. For each result it will duplicate the tag and it's contents. For the above example this means:
139
-
140
- <tr data-ruhl="_collection: user_list">
141
- <td data-ruhl="name">John Doe</td>
142
- <td data-ruhl="email">john@doe.com</td>
143
- </tr>
144
-
145
- is duplicated for each user in user_list.
146
-
147
- If user_list return an array of User objects like:
148
-
149
- [ User.create(:name => 'Rupert Boy', :email => 'rupert@stonean.com'),
150
- User.create(:name => 'Kaylee Girl', :email => 'kaylee@stonean.com'),
151
- User.create(:name => 'Monty Man', :email => 'monty@stonean.com')]
152
-
153
- <table id="aab">
154
- <tr>
155
- <td>Rupert Boy</td>
156
- <td>rupert@stonean.com</td>
157
- </tr>
158
- <tr>
159
- <td>Kaylee Girl</td>
160
- <td>kaylee@stonean.com</td>
161
- </tr>
162
- <tr>
163
- <td>Monty Man</td>
164
- <td>monty@stonean.com</td>
165
- </tr>
166
- </table>
167
-
168
-
169
-
170
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
171
- :: Using a Layout ::
172
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173
-
174
- Layout:
175
- <html>
176
- <head>
177
- <title>This is a title template</title>
178
- </head>
179
- <body>
180
- <div data-ruhl="_render_"></div>
181
- </body>
182
- </html>
183
-
184
- Fragment:
185
- <h1 data-ruhl="generate_h1">I am a templated headline</h1>
186
- <p data-ruhl="my_content">Lorem ipsum dolor sit amet</p>
187
-
188
- To use:
189
-
190
- RuHL::Engine.new(File.read(fragment), :layout => path_to_layout).render(self)
191
-
192
- Returns the expected result of parsed Layout w/ parsed Fragment.
193
-
194
- Note the use of the _render_ method. This is a 'special' method that
195
- RuHL uses to inject the results of the parsed fragment into the layout.
196
-
197
-
198
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
199
- :: Using a Partial ::
200
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201
-
202
- Main:
203
- <html>
204
- <head>
205
- <title>This is a title template</title>
206
- </head>
207
- <body>
208
- <div id="wrap">
209
- <div id="sidebar" data-ruhl="_partial: sidebar_partial">
210
- <h3>Sidebar links</h3>
211
- <ul>
212
- <li><a href="#">Link 1</a></li>
213
- <li><a href="#">Link 2</a></li>
214
- <li><a href="#">Link 3</a></li>
215
- <li><a href="#">Link 4</a></li>
216
- </ul>
217
- </div>
218
- <div id="main">
219
- <h1> My main content</h1>
220
- <p>Text designers would put here to test their layout</p>
221
- </div>
222
- </div>
223
- </body>
224
- </html>
225
-
226
- Sidebar:
227
- <h3>Real Sidebarlinks</h3>
228
- <ul>
229
- <li><a href="#">Real Link 1</a></li>
230
- <li><a href="#">Real Link 2</a></li>
231
- <li><a href="#">Real Link 3</a></li>
232
- <li><a href="#">Real Link 4</a></li>
233
- </ul>
234
-
235
- To use:
236
-
237
- RuHL::Engine.new(File.read(path_to_main)).render(self)
238
-
239
- Returns the expected result of parsed Main with sidebar div contents
240
- replaced with parsed sidebar partial contents.
241
-
242
- Note the use of the _partial key. This is a 'special' key that RuHL
243
- uses to inject the results of the parsed partial into the contents
244
- of the calling node.
245
-
246
-
247
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248
- :: Conditional display of block (_if)::
249
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
250
-
251
- <html>
252
- <head>
253
- <title>This is a title template</title>
254
- </head>
255
- <body>
256
- <h1>This is the header template</h1>
257
- <div data-ruhl="_if: users?">
258
- <table>
259
- <thead>
260
- <tr>
261
- <td>First Name</td>
262
- <td>Last Name</td>
263
- <td>Email</td>
264
- </tr>
265
- </thead>
266
- <tr data-ruhl="_collection: user_list">
267
- <td data-ruhl="first_name">Andrew</td>
268
- <td data-ruhl="last_name">Stone</td>
269
- <td data-ruhl="email">andy@stonean.com</td>
270
- </tr>
271
- </table>
272
- </div>
273
- </ul>
274
- </body>
275
- </html>
276
-
277
- if users? returns false then the div (including it's contents) are not shown
278
- on output.
279
-
280
-
281
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282
- :: Conditional display of tag (_if)::
283
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
284
-
285
- <html>
286
- <head>
287
- <title>This is a title template</title>
288
- </head>
289
- <body>
290
- <h1>This is the header template</h1>
291
- <table>
292
- <thead>
293
- <tr>
294
- <td>First Name</td>
295
- <td>Last Name</td>
296
- <td>Email</td>
297
- </tr>
298
- </thead>
299
- <tr data-ruhl="_collection: user_list">
300
- <td data-ruhl="first_name">Andrew</td>
301
- <td data-ruhl="last_name">Stone</td>
302
- <td data-ruhl="_if: email">andy@stonean.com</td>
303
- </tr>
304
- </table>
305
- </ul>
306
- </body>
307
- </html>
308
-
309
- if email.nil? then the td is not shown.
310
-
311
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
312
- :: Conditional display of tag (_unless)::
313
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314
-
315
- <html>
316
- <head>
317
- <title>This is a title template</title>
318
- </head>
319
- <body>
320
- <h1>This is the header template</h1>
321
- <table data-ruhl="_if: users?">
322
- <thead>
323
- <tr>
324
- <td>First Name</td>
325
- <td>Last Name</td>
326
- <td>Email</td>
327
- </tr>
328
- </thead>
329
- <tr data-ruhl="_collection: user_list">
330
- <td data-ruhl="first_name">Andrew</td>
331
- <td data-ruhl="last_name">Stone</td>
332
- <td data-ruhl="_if: email">andy@stonean.com</td>
333
- </tr>
334
- </table>
335
- <p data-ruhl="_unless: users?">No Users were found.</p>
336
- </ul>
337
- </body>
338
- </html>
339
-
340
- if users? == false then the "No Users were found" message appears.
341
-
342
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
343
- :: Scope object to tag block (_use)::
344
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
345
-
346
- <html>
347
- <head>
348
- <title>My Account</title>
349
- </head>
350
- <body>
351
- <div data-ruhl="_use: current_user">
352
- <h1> Editing <span data-ruhl="full_name"/></h1>
353
- <table>
354
- <thead>
355
- <tr>
356
- <td>First Name</td>
357
- <td>Last Name</td>
358
- <td>Email</td>
359
- </tr>
360
- </thead>
361
- <tr>
362
- <td data-ruhl="first_name">Andrew</td>
363
- <td data-ruhl="last_name">Stone</td>
364
- <td data-ruhl="_if: email">andy@stonean.com</td>
365
- </tr>
366
- </table>
367
- </div>
368
- </body>
369
- </html>
370
-
371
- The table row information will be replace with the current_user details.
372
-
373
- *Note: _use can not be used with _partial as it replaces the inner_html
374
-
375
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376
- :: Notes ::
377
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
378
-
379
- * No eval (I don't think eval is evil, it's just not the way this works)
380
-
381
- * The data-ruhl attribute is always removed from the output.
382
-
383
- * Since it's just HTML, syntax highlighting is built-in.
384
- For vim, just add this to your ~/.vimrc:
385
- au BufNewFile,BufRead *.ruhl set filetype=html
386
-
387
-
388
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
389
- :: TODO ::
390
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
391
-
392
- 1) Test more scenarios
7
+ http://stonean.com/page/ruhl
393
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.7
1
+ 0.10.0
data/lib/ruhl/engine.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Ruhl
2
2
  class Engine
3
- attr_reader :document, :scope, :layout, :layout_source,
4
- :local_object, :block_object
3
+ attr_reader :layout, :layout_source, :local_object, :block_object
4
+ attr_reader :document, :scope, :current_tag, :call_result, :ruhl_actions
5
5
 
6
6
  def initialize(html, options = {})
7
7
  @local_object = options[:local_object] || options[:object]
@@ -45,38 +45,37 @@ module Ruhl
45
45
  render_nodes Nokogiri::HTML( @layout_source || File.read(@layout) )
46
46
  end
47
47
 
48
- def render_partial(tag, code)
49
- file = execute_ruby(tag, code)
50
- raise PartialNotFoundError.new(file) unless File.exists?(file)
48
+ def render_partial
49
+ unless File.exists?(call_result)
50
+ raise PartialNotFoundError.new(call_result)
51
+ end
51
52
 
52
- render_nodes Nokogiri::HTML.fragment( File.read(file) )
53
+ render_nodes Nokogiri::HTML.fragment( File.read(call_result) )
53
54
  end
54
55
 
55
- def render_collection(tag, code, actions = nil)
56
- results = execute_ruby(tag, code)
57
-
58
- actions = actions.to_s.strip
56
+ def render_collection
57
+ actions = ruhl_actions.join(",").to_s.strip if ruhl_actions
59
58
 
60
- tag['data-ruhl'] = actions if actions.length > 0
61
- html = tag.to_html
59
+ current_tag['data-ruhl'] = actions if actions.length > 0
60
+ html = current_tag.to_html
62
61
 
63
- new_content = results.collect do |item|
62
+ new_content = call_result.collect do |item|
64
63
  # Call to_s on the item only if there are no other actions
65
64
  # and there are no other nested data-ruhls
66
- if actions.length == 0 && tag.xpath('.//*[@data-ruhl]').length == 0
67
- tag.inner_html = item.to_s
68
- tag.to_html
65
+ if actions.length == 0 && current_tag.xpath('.//*[@data-ruhl]').length == 0
66
+ current_tag.inner_html = item.to_s
67
+ current_tag.to_html
69
68
  else
70
69
  Ruhl::Engine.new(html, :local_object => item).render(scope)
71
70
  end
72
71
  end.to_s
73
72
 
74
- tag.swap(new_content)
73
+ current_tag.swap(new_content)
75
74
  end
76
75
 
77
- def render_block(tag, code)
78
- bo = execute_ruby(tag, code)
79
- Ruhl::Engine.new(tag.inner_html, :block_object => bo).render(scope)
76
+ def render_block
77
+ Ruhl::Engine.new(current_tag.inner_html,
78
+ :block_object => call_result).render(scope)
80
79
  end
81
80
 
82
81
  def render_nodes(nodes)
@@ -91,97 +90,117 @@ module Ruhl
91
90
 
92
91
  return if nodes.empty?
93
92
 
94
- tag = nodes.first
95
- code = tag.remove_attribute('data-ruhl')
96
- process_attribute(tag, code.value)
93
+ @current_tag = nodes.first
94
+
95
+ @ruhl_actions = current_tag.remove_attribute('data-ruhl').value.split(',')
96
+
97
+ process_attribute
97
98
 
98
99
  parse_doc(doc)
99
100
  end
100
101
 
101
- def process_attribute(tag, code)
102
- actions = code.split(',')
103
- actions.dup.each_with_index do |pair, ndx|
104
- attribute, value = pair.split(':')
105
-
106
- attribute.strip!
102
+ def process_attribute
103
+ catch(:done) do
104
+ ruhl_actions.dup.each_with_index do |action, ndx|
105
+ # Remove action from being applied twice.
106
+ ruhl_actions.delete_at(ndx)
107
+
108
+ process_action(action)
109
+ end
110
+ end
111
+ end
112
+
113
+ def process_action(action)
114
+ attribute, value = action.split(':')
107
115
 
108
- if value.nil?
109
- results = execute_ruby(tag, attribute)
110
- process_results(tag, results)
116
+ code = (value || attribute)
117
+ @call_result = execute_ruby(code.strip)
118
+
119
+ if value.nil?
120
+ process_results
121
+ else
122
+ if attribute =~ /^_/
123
+ process_ruhl(attribute, value)
111
124
  else
112
- value.strip!
113
-
114
- unless attribute =~ /^_/
115
- tag[attribute] = execute_ruby(tag, value).to_s
116
- else
117
- case attribute
118
- when "_use"
119
- tag.inner_html = render_block(tag, value)
120
- when "_partial"
121
- tag.inner_html = render_partial(tag, value)
122
- when "_collection"
123
- actions.delete_at(ndx)
124
- render_collection(tag, value, actions.join(','))
125
- return
126
- when "_if"
127
- return unless process_if(tag, value)
128
- when "_unless"
129
- return if process_unless(tag, value)
130
- end
131
- end
125
+ current_tag[attribute] = call_result.to_s
132
126
  end
133
127
  end
134
128
  end
129
+
130
+ def process_ruhl(attribute, value)
131
+ case attribute
132
+ when "_use_if"
133
+ ruhl_if { ruhl_use }
134
+ when "_use", "_collection"
135
+ ruhl_use
136
+ when "_partial"
137
+ current_tag.inner_html = render_partial
138
+ when "_if"
139
+ ruhl_if
140
+ when "_unless"
141
+ ruhl_unless
142
+ end
143
+ end
144
+
145
+ def ruhl_use
146
+ if call_result.kind_of?(Enumerable) and !call_result.instance_of?(String)
147
+ render_collection
148
+ throw :done
149
+ else
150
+ current_tag.inner_html = render_block
151
+ end
152
+ end
135
153
 
136
- def process_if(tag, value)
137
- contents = execute_ruby(tag, value)
138
- if contents
139
- process_results(tag, contents) unless contents == true
140
- true
154
+ def ruhl_if
155
+ if stop_processing?
156
+ current_tag.remove
157
+ throw :done
141
158
  else
142
- tag.remove
143
- false
159
+ if continue_processing?
160
+ yield if block_given?
161
+ else
162
+ process_results
163
+ end
144
164
  end
145
165
  end
146
166
 
147
- def process_unless(tag, value)
148
- contents = execute_ruby(tag, value)
149
- if contents
150
- tag.remove
151
- true
152
- else
153
- false
167
+ def ruhl_unless
168
+ if call_result
169
+ unless call_result_empty?
170
+ current_tag.remove
171
+ throw :done
172
+ end
154
173
  end
155
174
  end
156
175
 
157
- def process_results(tag, results)
158
- if results.is_a?(Hash)
159
- results.each do |key, value|
176
+ def process_results
177
+ if call_result.is_a?(Hash)
178
+ call_result.each do |key, value|
160
179
  if key == :inner_html
161
- tag.inner_html = value.to_s
180
+ current_tag.inner_html = value.to_s
162
181
  else
163
- tag[key.to_s] = value.to_s
182
+ current_tag[key.to_s] = value.to_s
164
183
  end
165
184
  end
166
185
  else
167
- tag.inner_html = results.to_s
186
+ current_tag.inner_html = call_result.to_s
168
187
  end
169
188
  end
170
189
 
171
- def execute_ruby(tag, code)
172
- unless code == '_render_'
173
- if local_object && local_object.respond_to?(code)
174
- local_object.send(code)
175
- elsif block_object && block_object.respond_to?(code)
190
+ def execute_ruby(code)
191
+ if code == '_render_'
192
+ _render_
193
+ else
194
+ if block_object && block_object.respond_to?(code)
176
195
  block_object.send(code)
196
+ elsif local_object && local_object.respond_to?(code)
197
+ local_object.send(code)
177
198
  else
178
199
  scope.send(code)
179
200
  end
180
- else
181
- _render_
182
201
  end
183
202
  rescue NoMethodError => e
184
- log_context(tag,code)
203
+ log_context(code)
185
204
  raise e
186
205
  end
187
206
 
@@ -190,10 +209,24 @@ module Ruhl
190
209
  @scope = current_scope
191
210
  end
192
211
 
193
- def log_context(tag,code)
212
+ def stop_processing?
213
+ call_result.nil? ||
214
+ call_result == false ||
215
+ call_result_empty?
216
+ end
217
+
218
+ def continue_processing?
219
+ call_result == true || !call_result_empty?
220
+ end
221
+
222
+ def call_result_empty?
223
+ call_result.kind_of?(Enumerable) && call_result.empty?
224
+ end
225
+
226
+ def log_context(code)
194
227
  Ruhl.logger.error <<CONTEXT
195
228
  Context:
196
- tag : #{tag.inspect}
229
+ tag : #{current_tag.inspect}
197
230
  code : #{code.inspect}
198
231
  local_object : #{local_object.inspect}
199
232
  block_object : #{block_object.inspect}
data/ruhl.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruhl}
8
- s.version = "0.9.7"
8
+ s.version = "0.10.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew Stone"]
12
- s.date = %q{2009-10-18}
12
+ s.date = %q{2009-10-24}
13
13
  s.description = %q{Make your HTML dynamic with the addition of a data-ruhl attribute.}
14
14
  s.email = %q{andy@stonean.com}
15
15
  s.extra_rdoc_files = [
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  "spec/html/fragment.html",
33
33
  "spec/html/hash.html",
34
34
  "spec/html/if.html",
35
+ "spec/html/if_on_collection.html",
35
36
  "spec/html/layout.html",
36
37
  "spec/html/loop.html",
37
38
  "spec/html/main_with_form.html",
@@ -40,6 +41,7 @@ Gem::Specification.new do |s|
40
41
  "spec/html/seo.html",
41
42
  "spec/html/sidebar.html",
42
43
  "spec/html/use.html",
44
+ "spec/html/use_if.html",
43
45
  "spec/rcov.opts",
44
46
  "spec/ruhl_spec.rb",
45
47
  "spec/spec.opts",
@@ -0,0 +1,23 @@
1
+ <html>
2
+ <head>
3
+ <title>This is a title template</title>
4
+ </head>
5
+ <body>
6
+ <h1>This is the header template</h1>
7
+ <table data-ruhl="_if: user_list">
8
+ <thead>
9
+ <tr>
10
+ <td>First Name</td>
11
+ <td>Last Name</td>
12
+ <td>Email</td>
13
+ </tr>
14
+ </thead>
15
+ <tr data-ruhl="_collection: user_list">
16
+ <td data-ruhl="first_name">Andrew</td>
17
+ <td data-ruhl="last_name">Stone</td>
18
+ <td data-ruhl="_if: email">andy@stonean.com</td>
19
+ </tr>
20
+ </table>
21
+ <p data-ruhl="_unless: user_list, no_users_message"/>
22
+ </body>
23
+ </html>
@@ -0,0 +1,28 @@
1
+ <html>
2
+ <head>
3
+ <title>This is a title template</title>
4
+ </head>
5
+ <body>
6
+ <div id="sidebar" data-ruhl="_use_if: user">
7
+ <h1>My Account</h1>
8
+ <form action="/account" class="edit_user" id="edit_user" method="post">
9
+
10
+ <label for='user_first_name'>First Name:</label>
11
+ <input id="user_first_name" name="user[first_name]" size="30" type="text"
12
+ data-ruhl="value: first_name" />
13
+
14
+ <label for='user_last_name'>Last Name:</label>
15
+ <input id="user_last_name" name="user[last_name]" size="30" type="text"
16
+ data-ruhl="value: last_name" />
17
+
18
+ <label for='user_email'>Email:</label>
19
+ <input id="user_email" name="user[email]" size="30" type="text"
20
+ data-ruhl="value: email" />
21
+
22
+ <div class='btn_row'>
23
+ <input id="user_submit" name="commit" type="submit" value="Login" />
24
+ </div>
25
+ </form>
26
+ </div>
27
+ </body>
28
+ </html>
data/spec/ruhl_spec.rb CHANGED
@@ -82,11 +82,35 @@ describe Ruhl do
82
82
  end
83
83
  end
84
84
 
85
+ shared_examples_for "if with no users" do
86
+ it "table should not render" do
87
+ nodes = @doc.xpath('/html/body//*')
88
+ nodes.children.length.should == 2
89
+ nodes.children[0].to_s.should == "This is the header template"
90
+ end
91
+
92
+ it "no user message should render" do
93
+ nodes = @doc.xpath('/html/body//*')
94
+ nodes.children[1].to_s.should == @co.no_users_message
95
+ end
96
+ end
97
+
98
+ shared_examples_for "if with users" do
99
+ it "table should render" do
100
+ nodes = @doc.xpath('/html/body//*')
101
+ nodes.children.length.should > 1
102
+
103
+ table = @doc.xpath('/html/body/table/tr//td')
104
+ table.children[12].to_s.should == "NoMail"
105
+ table.children[13].to_s.should == "Man"
106
+ end
107
+ end
108
+
85
109
  describe "if.html" do
86
- describe "no users" do
110
+ describe "users? is false" do
87
111
  before do
88
112
  class ContextObject
89
- def users?(tag = nil)
113
+ def users?
90
114
  false
91
115
  end
92
116
  end
@@ -95,22 +119,13 @@ describe Ruhl do
95
119
  @doc = create_doc
96
120
  end
97
121
 
98
- it "table should not render" do
99
- nodes = @doc.xpath('/html/body//*')
100
- nodes.children.length.should == 2
101
- nodes.children[0].to_s.should == "This is the header template"
102
- end
103
-
104
- it "no user message should render" do
105
- nodes = @doc.xpath('/html/body//*')
106
- nodes.children[1].to_s.should == @co.no_users_message
107
- end
122
+ it_should_behave_like "if with no users"
108
123
  end
109
124
 
110
- describe "has users" do
125
+ describe "users? is true" do
111
126
  before do
112
127
  class ContextObject
113
- def users?(tag = nil)
128
+ def users?
114
129
  true
115
130
  end
116
131
  end
@@ -119,14 +134,45 @@ describe Ruhl do
119
134
  @doc = create_doc
120
135
  end
121
136
 
122
- it "table should render" do
123
- nodes = @doc.xpath('/html/body//*')
124
- nodes.children.length.should > 1
137
+ it_should_behave_like "if with users"
138
+ end
139
+ end
140
+
141
+ describe "if_on_collection.html" do
142
+ describe "user_list is empty" do
143
+ before do
144
+ class ContextObject
145
+ def user_list
146
+ []
147
+ end
148
+ end
149
+
150
+ @html = File.read html(:if_on_collection)
151
+ @doc = create_doc
152
+ end
153
+
154
+ it_should_behave_like "if with no users"
155
+ end
156
+
157
+ describe "user_list is not empty" do
158
+ before do
159
+ class ContextObject
160
+ def user_list
161
+ [
162
+ TestUser.new('Jane', 'Doe', 'jane@stonean.com'),
163
+ TestUser.new('John', 'Joe', 'john@stonean.com'),
164
+ TestUser.new('Jake', 'Smo', 'jake@stonean.com'),
165
+ TestUser.new('Paul', 'Tin', 'paul@stonean.com'),
166
+ TestUser.new('NoMail', 'Man')
167
+ ]
168
+ end
169
+ end
125
170
 
126
- table = @doc.xpath('/html/body/table/tr//td')
127
- table.children[12].to_s.should == "NoMail"
128
- table.children[13].to_s.should == "Man"
171
+ @html = File.read html(:if_on_collection)
172
+ @doc = create_doc
129
173
  end
174
+
175
+ it_should_behave_like "if with users"
130
176
  end
131
177
  end
132
178
 
@@ -177,12 +223,7 @@ describe Ruhl do
177
223
  end
178
224
  end
179
225
 
180
- describe "use.html" do
181
- before do
182
- @html = File.read html(:use)
183
- @doc = create_doc
184
- end
185
-
226
+ shared_examples_for "if with user" do
186
227
  it "first name will be set" do
187
228
  @doc.xpath('/html/body/div//input')[0]['value'].should == "Jane"
188
229
  end
@@ -195,6 +236,24 @@ describe Ruhl do
195
236
  @doc.xpath('/html/body/div//input')[2]['value'].should == "jane@stonean.com"
196
237
  end
197
238
  end
239
+
240
+ describe "use.html" do
241
+ before do
242
+ @html = File.read html(:use)
243
+ @doc = create_doc
244
+ end
245
+
246
+ it_should_behave_like "if with user"
247
+ end
248
+
249
+ describe "use_if.html" do
250
+ before do
251
+ @html = File.read html(:use_if)
252
+ @doc = create_doc
253
+ end
254
+
255
+ it_should_behave_like "if with user"
256
+ end
198
257
 
199
258
  describe "collection_of_strings.html" do
200
259
  before do
data/spec/spec_helper.rb CHANGED
@@ -29,47 +29,47 @@ class TestUser
29
29
  @nicknames = ['Auntie','Pattern']
30
30
  end
31
31
 
32
- def radio_input(tag = nil)
32
+ def radio_input
33
33
  { :inner_html => first_name, :id => "user_#{id.to_s}",
34
34
  :name => "user[id]", :value => last_name.downcase}
35
35
  end
36
36
  end
37
37
 
38
- def user(tag = nil)
38
+ def user
39
39
  TestUser.new('Jane', 'Doe', 'jane@stonean.com')
40
40
  end
41
41
 
42
42
 
43
43
  class ContextObject
44
- def generate_h1(tag = nil)
44
+ def generate_h1
45
45
  "data from presenter"
46
46
  end
47
47
 
48
- def data_from_method(tag = nil)
48
+ def data_from_method
49
49
  "I am data from a method"
50
50
  end
51
51
 
52
- def generate_description(tag = nil)
52
+ def generate_description
53
53
  "I am a custom meta description"
54
54
  end
55
55
 
56
- def generate_keywords(tag = nil)
56
+ def generate_keywords
57
57
  "I, am, custom, keywords"
58
58
  end
59
59
 
60
- def my_content(tag = nil)
60
+ def my_content
61
61
  "hello from my content."
62
62
  end
63
63
 
64
- def sidebar_partial(tag = nil)
64
+ def sidebar_partial
65
65
  html(:sidebar)
66
66
  end
67
67
 
68
- def form_partial(tag = nil)
68
+ def form_partial
69
69
  html(:form)
70
70
  end
71
71
 
72
- def user_list(tag = nil)
72
+ def user_list
73
73
  [
74
74
  TestUser.new('Jane', 'Doe', 'jane@stonean.com'),
75
75
  TestUser.new('John', 'Joe', 'john@stonean.com'),
@@ -79,15 +79,15 @@ class ContextObject
79
79
  ]
80
80
  end
81
81
 
82
- def users?(tag = nil)
82
+ def users?
83
83
  true
84
84
  end
85
85
 
86
- def no_users_message(tag = nil)
86
+ def no_users_message
87
87
  "Sorry no users found"
88
88
  end
89
89
 
90
- def states_for_select(tag = nil)
90
+ def states_for_select
91
91
  state = Struct.new(:abbr, :name)
92
92
  [ state.new('AL', 'Alabama'),
93
93
  state.new('AK', 'Alaska'),
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruhl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Stone
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-18 00:00:00 -04:00
12
+ date: 2009-10-24 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -57,6 +57,7 @@ files:
57
57
  - spec/html/fragment.html
58
58
  - spec/html/hash.html
59
59
  - spec/html/if.html
60
+ - spec/html/if_on_collection.html
60
61
  - spec/html/layout.html
61
62
  - spec/html/loop.html
62
63
  - spec/html/main_with_form.html
@@ -65,6 +66,7 @@ files:
65
66
  - spec/html/seo.html
66
67
  - spec/html/sidebar.html
67
68
  - spec/html/use.html
69
+ - spec/html/use_if.html
68
70
  - spec/rcov.opts
69
71
  - spec/ruhl_spec.rb
70
72
  - spec/spec.opts