hobo 0.6.1 → 0.6.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.
Files changed (47) hide show
  1. data/bin/hobo +3 -2
  2. data/hobo_files/plugin/CHANGES.txt +299 -2
  3. data/hobo_files/plugin/Rakefile +12 -10
  4. data/hobo_files/plugin/generators/hobo/templates/guest.rb +1 -13
  5. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +11 -7
  6. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +1 -0
  7. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +1 -1
  8. data/hobo_files/plugin/generators/hobo_rapid/templates/lowpro.js +405 -0
  9. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +1 -1
  10. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +1 -9
  11. data/hobo_files/plugin/init.rb +5 -0
  12. data/hobo_files/plugin/lib/active_record/has_many_association.rb +1 -1
  13. data/hobo_files/plugin/lib/extensions.rb +26 -5
  14. data/hobo_files/plugin/lib/extensions/test_case.rb +1 -1
  15. data/hobo_files/plugin/lib/hobo.rb +37 -11
  16. data/hobo_files/plugin/lib/hobo/authenticated_user.rb +7 -2
  17. data/hobo_files/plugin/lib/hobo/authentication_support.rb +7 -6
  18. data/hobo_files/plugin/lib/hobo/composite_model.rb +5 -0
  19. data/hobo_files/plugin/lib/hobo/controller.rb +4 -4
  20. data/hobo_files/plugin/lib/hobo/dryml.rb +5 -5
  21. data/hobo_files/plugin/lib/hobo/dryml/part_context.rb +3 -6
  22. data/hobo_files/plugin/lib/hobo/dryml/template.rb +16 -15
  23. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +24 -20
  24. data/hobo_files/plugin/lib/hobo/email_address.rb +4 -0
  25. data/hobo_files/plugin/lib/hobo/field_spec.rb +2 -1
  26. data/hobo_files/plugin/lib/hobo/guest.rb +21 -0
  27. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +42 -2
  28. data/hobo_files/plugin/lib/hobo/http_parameters.rb +225 -0
  29. data/hobo_files/plugin/lib/hobo/model.rb +55 -37
  30. data/hobo_files/plugin/lib/hobo/model_controller.rb +151 -151
  31. data/hobo_files/plugin/lib/hobo/model_queries.rb +30 -5
  32. data/hobo_files/plugin/lib/hobo/user_controller.rb +27 -16
  33. data/hobo_files/plugin/lib/hobo/where_fragment.rb +6 -1
  34. data/hobo_files/plugin/tags/rapid.dryml +88 -58
  35. data/hobo_files/plugin/tags/rapid_document_tags.dryml +5 -5
  36. data/hobo_files/plugin/tags/rapid_editing.dryml +3 -3
  37. data/hobo_files/plugin/tags/rapid_forms.dryml +35 -26
  38. data/hobo_files/plugin/tags/rapid_navigation.dryml +13 -12
  39. data/hobo_files/plugin/tags/rapid_pages.dryml +35 -31
  40. data/hobo_files/plugin/tags/rapid_plus.dryml +41 -0
  41. data/hobo_files/plugin/tags/rapid_support.dryml +18 -9
  42. data/hobo_files/plugin/tasks/dump_fixtures.rake +61 -0
  43. metadata +7 -11
  44. data/hobo_files/plugin/spec/fixtures/users.yml +0 -9
  45. data/hobo_files/plugin/spec/spec.opts +0 -6
  46. data/hobo_files/plugin/spec/spec_helper.rb +0 -28
  47. data/hobo_files/plugin/spec/unit/hobo/dryml/template_spec.rb +0 -650
@@ -1,9 +0,0 @@
1
- # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
- one:
3
- id: 1
4
- created_at: 2007-06-21 13:10:55
5
- updated_at: 2007-06-21 13:10:55
6
- two:
7
- id: 2
8
- created_at: 2007-06-21 13:10:55
9
- updated_at: 2007-06-21 13:10:55
@@ -1,6 +0,0 @@
1
- --colour
2
- --format
3
- progress
4
- --loadby
5
- mtime
6
- --reverse
@@ -1,28 +0,0 @@
1
- ENV['RAILS_ENV'] ||= 'mysql'
2
- require File.dirname(__FILE__) + '/rails_root/config/environment.rb'
3
-
4
- # Run the migrations
5
- ActiveRecord::Migrator.migrate("#{RAILS_ROOT}/db/migrate")
6
-
7
- require 'spec/rails'
8
-
9
- Spec::Runner.configure do |config|
10
- config.use_transactional_fixtures = true
11
- config.use_instantiated_fixtures = false
12
- config.fixture_path = File.dirname(__FILE__) + "/fixtures/"
13
- config.before(:each, :behaviour_type => :controller) do
14
- raise_controller_errors
15
- end
16
-
17
- # You can declare fixtures for each behaviour like this:
18
- # describe "...." do
19
- # fixtures :table_a, :table_b
20
- #
21
- # Alternatively, if you prefer to declare them only once, you can
22
- # do so here, like so ...
23
- #
24
- # config.global_fixtures = :table_a, :table_b
25
- #
26
- # If you declare global fixtures, be aware that they will be declared
27
- # for all of your examples, even those that don't use them.
28
- end
@@ -1,650 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
-
3
- Template = Hobo::Dryml::Template
4
- DrymlException = Hobo::Dryml::DrymlException
5
-
6
- describe Template do
7
-
8
- # --- Tag Compilation Examples --- #
9
-
10
- # --- Compilation: Calling Block Tags --- #
11
-
12
- it "should compile block-tag calls as method calls" do
13
- compile_dryml("<foo/>").should == "<%= foo() %>"
14
- end
15
-
16
- it "should compile attributes as keyword parameters" do
17
- compile_dryml("<foo a='1' b='2'/>").should == '<%= foo({:a => "1", :b => "2"}) %>'
18
- end
19
-
20
- it "should compile code attributes as ruby code" do
21
- compile_dryml("<foo a='&1 + 2'/>").should == '<%= foo({:a => (1 + 2)}) %>'
22
- end
23
-
24
- it "should compile block-tag attributes with no RHS as passing `true`" do
25
- compile_dryml("<foo a/>").should == '<%= foo({:a => (true)}) %>'
26
- end
27
-
28
- it "should compile content of a block-tag call as a Ruby block" do
29
- compile_dryml("<foo>the body</foo>").should == "<% _output(foo() do |foo_default_tagbody| %>the body<% end) %>"
30
- end
31
-
32
- it "should support <default_tagbody/> inside the content of a block-tag" do
33
- compile_dryml("<foo>!!<default_tagbody/>??</foo>").should ==
34
- "<% _output(foo() do |foo_default_tagbody| %>!!<% foo_default_tagbody && foo_default_tagbody.call %>??<% end) %>"
35
- end
36
-
37
- it "should support the 'for' attribute on <default_tagbody/>" do
38
- compile_dryml("<x><y>123<default_tagbody for='x'/>456</y></x>").should ==
39
- "<% _output(x() do |x_default_tagbody| %><% _output(y() do |y_default_tagbody| %>" +
40
- "123<% x_default_tagbody && x_default_tagbody.call %>456" +
41
- "<% end) %><% end) %>"
42
- end
43
-
44
- it "should allow :foo as a shorthand for field='foo' on block tags" do
45
- compile_dryml("<foo:name/>").should == '<%= foo({:field => "name"}) %>'
46
- end
47
-
48
- it "should allow :title as a shorthand for field='title' on block tags (title is a static tag)" do
49
- compile_dryml("<foo:name/>").should == '<%= foo({:field => "name"}) %>'
50
- end
51
-
52
- it "should allow close tags to ommit the :field_name part" do
53
- compile_dryml("<foo:name></foo>").should == '<%= foo({:field => "name"}) %>'
54
- end
55
-
56
- it "should compile block-tag calls with merge_attrs" do
57
- compile_dryml("<foo merge_attrs/>").should == "<%= foo({}.merge((attributes) || {})) %>"
58
- compile_dryml("<foo a='1' merge_attrs/>").should == '<%= foo({:a => "1"}.merge((attributes) || {})) %>'
59
- end
60
-
61
- # --- Compilation: Defining Block Tags --- #
62
-
63
- it "should compile defs with lower-case names as block tags" do
64
- compile_def("<def tag='foo'></def>").should ==
65
- "<% def foo(all_attributes={}, &__block__); " +
66
- "parameters = nil; " +
67
- "_tag_context(all_attributes, __block__) do |tagbody| attributes, = _tag_locals(all_attributes, []) %>" +
68
- "<% _erbout; end; end %>"
69
- end
70
-
71
- it "should compile attrs in defs as local variables" do
72
- compile_def("<def tag='foo' attrs='a, b'></def>").should ==
73
- "<% def foo(all_attributes={}, &__block__); " +
74
- "parameters = nil; " +
75
- "_tag_context(all_attributes, __block__) do |tagbody| " +
76
- "a, b, attributes, = _tag_locals(all_attributes, [:a, :b]) %>" +
77
- "<% _erbout; end; end %>"
78
- end
79
-
80
- it "should allow a default tagbody to be given inside the <tagbody> tag" do
81
- compile_def("<def tag='foo'>123 <tagbody>blah</tagbody> 456</def>").should ==
82
- "<% def foo(all_attributes={}, &__block__); " +
83
- "parameters = nil; " +
84
- "_tag_context(all_attributes, __block__) do |tagbody| attributes, = _tag_locals(all_attributes, []) %>" +
85
- "123 " +
86
- "<% _output(do_tagbody(tagbody, {}, proc { %>blah<% })) %>" +
87
- " 456" +
88
- "<% _erbout; end; end %>"
89
- end
90
-
91
- # --- Compilation: Defining Templates --- #
92
-
93
- it "should compile defs with cap names as templates" do
94
- # Note the presence of the `parameters` param, which block-tags don't have
95
- compile_def("<def tag='Foo'></def>").should ==
96
- "<% def Foo(all_attributes={}, all_parameters={}, &__block__); " +
97
- "parameters = all_parameters - []; " +
98
- "_tag_context(all_attributes, __block__) do |tagbody| attributes, = _tag_locals(all_attributes, []) %>" +
99
- "<% _erbout; end; end %>"
100
- end
101
-
102
- it "should dissallow `param` outside of template definitions" do
103
- proc { compile_dryml("<foo param/>") }.should raise_error(DrymlException)
104
- end
105
-
106
- it "should compile param tag-calls as calls to `call_block_tag_parameter`" do
107
- compile_in_template("<foo param a='1'/>").should == '<%= call_block_tag_parameter(:foo, {:a => "1"}, all_parameters[:foo]) %>'
108
- end
109
-
110
- it "should compile with support for named params" do
111
- compile_in_template("<foo param='zap'/>").should == "<%= call_block_tag_parameter(:foo, {}, all_parameters[:zap]) %>"
112
- end
113
-
114
- it "should compile a param tag-call with a body" do
115
- compile_in_template("<foo param>abc</foo>").should ==
116
- "<% _output(call_block_tag_parameter(:foo, {}, all_parameters[:foo]) do |foo_default_tagbody| %>abc<% end) %>"
117
- end
118
-
119
- it "should compile a param tag-call with a body and a call to <default_tagbody/>" do
120
- compile_in_template("<foo param>!!<default_tagbody/>!!</foo>").should ==
121
- "<% _output(call_block_tag_parameter(:foo, {}, all_parameters[:foo]) do |foo_default_tagbody| %>" +
122
- "!!<% foo_default_tagbody && foo_default_tagbody.call %>!!<% end) %>"
123
- end
124
-
125
- it "should compile param template-calls as calls to `call_template_parameter`" do
126
- compile_in_template("<Foo param/>").should ==
127
- "<% _output(call_template_parameter(:Foo, {}, {}, all_parameters[:Foo])) %>"
128
- end
129
-
130
- it "should compile param template-calls with parameters as calls to `call_template_parameter`" do
131
- compile_in_template("<Foo param><a x='1'/></Foo>").should ==
132
- '<% _output(call_template_parameter(:Foo, {}, {:a => proc { {:x => "1"} }, }, all_parameters[:Foo])) %>'
133
- end
134
-
135
- it "should compile template parameters with param" do
136
- compile_in_template("<Foo><abc param/></Foo>").should ==
137
- '<% _output(Foo({}, {:abc => merge_option_procs(proc { {} }, all_parameters[:abc]), })) %>'
138
- end
139
-
140
- it "should compile template parameters with named params" do
141
- compile_in_template("<Foo><abc param='x'/></Foo>").should ==
142
- '<% _output(Foo({}, {:abc => merge_option_procs(proc { {} }, all_parameters[:x]), })) %>'
143
- end
144
-
145
- it "should compile template parameters with param and attributes" do
146
- compile_in_template("<Foo><abc param='x' a='b'/></Foo>").should ==
147
- '<% _output(Foo({}, {:abc => merge_option_procs(proc { {:a => "b"} }, all_parameters[:x]), })) %>'
148
- end
149
-
150
- it "should compile template parameters with param and a tag body" do
151
- compile_in_template("<Foo><abc param>ha!</abc></Foo>").should ==
152
- '<% _output(Foo({}, {:abc => merge_option_procs(' +
153
- 'proc { {:tagbody => proc {|abc_default_tagbody| new_context { %>ha!<% } } } }, all_parameters[:abc]), })) %>'
154
- end
155
-
156
- it "should compile template parameters which are template calls themselves" do
157
- compile_in_template("<Foo><Baa param x='1'/></Foo>").should ==
158
- '<% _output(Foo({}, {:Baa => merge_template_parameter_procs(proc { [{:x => "1"}, {}] }, all_parameters[:Baa]), })) %>'
159
- end
160
-
161
- it "should compile template parameters which are templates themselves with their own parameters" do
162
- compile_in_template("<Foo><Baa param><x>hello</x></Baa></Foo>").should ==
163
- '<% _output(Foo({}, {:Baa => merge_template_parameter_procs(' +
164
- 'proc { [{}, {:x => proc { {:tagbody => proc {|x_default_tagbody| new_context { %>hello<% } } } }, }] }, all_parameters[:Baa]), })) %>'
165
- end
166
-
167
- # --- Compilation: Calling Templates --- #
168
-
169
- it "should compile template calls as method calls" do
170
- compile_dryml("<Foo/>").should == "<% _output(Foo({}, {})) %>"
171
- end
172
-
173
- it "should compile attributes on template calls as keyword parameters" do
174
- compile_dryml("<Foo a='1' b='2'/>").should == '<% _output(Foo({:a => "1", :b => "2"}, {})) %>'
175
- end
176
-
177
- it "should compile template parameters as procs" do
178
- compile_dryml("<Foo><x>hello</x><y>world</y></Foo>").should ==
179
- '<% _output(Foo({}, {' +
180
- ':x => proc { {:tagbody => proc {|x_default_tagbody| new_context { %>hello<% } } } }, ' +
181
- ':y => proc { {:tagbody => proc {|y_default_tagbody| new_context { %>world<% } } } }, })) %>'
182
- end
183
-
184
- it "should compile template parameters with attributes" do
185
- compile_dryml("<Foo><abc x='1'>hello</abc></Foo>").should ==
186
- '<% _output(Foo({}, {:abc => proc { {:x => "1", :tagbody => proc {|abc_default_tagbody| new_context { %>hello<% } } } }, })) %>'
187
- end
188
-
189
- it "should allow :foo as a shorthand for field='foo' on template tags" do
190
- compile_dryml("<Foo:name/>").should == '<% _output(Foo({:field => "name"}, {})) %>'
191
- end
192
-
193
- it "should dissallow tag-bodies on template calls" do
194
- proc { compile_dryml("<Foo>this is a tag body</Foo>") }.should raise_error(DrymlException)
195
- end
196
-
197
- it "should dissallow tag-bodies on nested template calls" do
198
- proc { compile_dryml("<Foo><Baa>this is a tag body</Baa></Foo>") }.should raise_error(DrymlException)
199
- end
200
-
201
- it "should compile template parameters which are themselves templates" do
202
- # Template parameters which are themselves templates are procs
203
- # that return a pair of hashes, the first is the attributes to the
204
- # template, the second is the sub-template procs
205
- compile_dryml("<Foo><Baa x='1'><a>hello</a></Baa></Foo>").should ==
206
- '<% _output(Foo({}, ' +
207
- '{:Baa => proc { [{:x => "1"}, {:a => proc { {:tagbody => proc {|a_default_tagbody| new_context { %>hello<% } } } }, }] }, })) %>'
208
- end
209
-
210
- it "should compile 'replace' parameters" do
211
- compile_dryml("<Page><head replace>abc</head></Page>").should ==
212
- '<% _output(Page({}, {:head => proc {|head__default| new_context { %>abc<% } }, })) %>'
213
- end
214
-
215
- it "should compile 'replace' parameters with a default parameter call" do
216
- compile_dryml("<Page><head replace>abc <head restore>blah</head></head></Page>").should ==
217
-
218
- '<% _output(Page({}, {:head => proc {|head__default| new_context { %>abc ' +
219
- '<% _output(head__default.call_with_block({}) do |head_default_tagbody| %>blah<% end) %>' +
220
- '<% } }, })) %>'
221
- end
222
-
223
- it "should compile 'replace' template parameters with a default parameter call" do
224
- compile_dryml("<Page><Head replace>abc <Head restore/></Head></Page>").should ==
225
-
226
- '<% _output(Page({}, {:Head => proc {|Head__default| new_context { %>abc ' +
227
- '<% _output(Head__default.call({}, {})) %>' +
228
- '<% } }, })) %>'
229
- end
230
-
231
- # --- Tag Evalutation Examples --- #
232
-
233
-
234
- # --- Static Tags --- #
235
-
236
- it "should pass through tags declared as static" do
237
- "p".should be_in(Hobo.static_tags)
238
- eval_dryml("<p>abc</p>").should == "<p>abc</p>"
239
- eval_dryml("<p x='1' y='2'>abc</p>").should == "<p x='1' y='2'>abc</p>"
240
- end
241
-
242
- it "should pass through attributes with no rhs on static tags" do
243
- "p".should be_in(Hobo.static_tags)
244
- eval_dryml("<p foo baa>abc</p>").should == "<p foo baa>abc</p>"
245
- end
246
-
247
- it "should support attribute merging on static tags" do
248
- eval_dryml(%(<p class="big" id="x" merge_attrs="&{:class => 'small', :id => 'y', :a => 'b'}"/>)).
249
- should be_dom_equal_to('<p class="big small" id="y" a="b"/>')
250
- end
251
-
252
- it "should support attribute merging of all extra attributes on static tags" do
253
- eval_dryml(%(<def tag="x"><p class="big" id="x" merge_attrs/></def>
254
- <x class='small' id='y' a='b'/>)).
255
- should be_dom_equal_to('<p class="big small" id="y" a="b"/>')
256
- end
257
-
258
-
259
- # --- Block Tags --- #
260
-
261
-
262
- def eval_with_defs(dryml)
263
- eval_dryml(<<-END + dryml).strip
264
- <def tag="t">plain tag</def>
265
-
266
- <def tag="t_attr" attrs="x">it is <%= x %></def>
267
-
268
- <def tag="t_body">( <tagbody>hmm</tagbody> )</def>
269
-
270
- <def tag="merge_attrs_example"><p merge_attrs>hi</p></def>
271
- END
272
- end
273
-
274
- it "should call block tags" do
275
- eval_with_defs("<t/>").should == "plain tag"
276
- end
277
-
278
-
279
- it "should call block tags passing attributes" do
280
- eval_with_defs("<t_attr x='10'/>").should == "it is 10"
281
- end
282
-
283
- it "should call block tags with a body" do
284
- eval_with_defs("<t_body>foo</t_body>").should == "( foo )"
285
- end
286
-
287
- it "should allow tagbody to have a default" do
288
- eval_with_defs("<t_body/>").should == "( hmm )"
289
- end
290
-
291
- it "should provide access to the default tagbody when overriding the body" do
292
- eval_with_defs("<t_body>[<default_tagbody/>]</t_body>").should == "( [hmm] )"
293
- end
294
-
295
- it "should support merge_attrs on static tags" do
296
- eval_with_defs('<merge_attrs_example class="x"/>').should == '<p class="x">hi</p>'
297
- end
298
-
299
- it "should make the declared attributes available via the 'attrs_for' method" do
300
- eval_with_defs('<%= attrs_for(:t_attr).inspect %>').should == '[:x]'
301
- end
302
-
303
-
304
-
305
- # --- Template Tags --- #
306
-
307
- def eval_with_templates(dryml)
308
- eval_dryml(<<-END + dryml).strip
309
- <def tag="defined" attrs="a, b">a is <%= a %>, b is <%= b %>, body is <tagbody/></def>
310
-
311
- <def tag="T">plain template</def>
312
-
313
- <def tag="StaticMerge"><p>a <b name="big" param>bold</b> word</p></def>
314
-
315
- <def tag="EmptyStaticMerge"><img name="big" src="..." param/></def>
316
-
317
- <def tag="DefTagMerge">foo <defined param b="3">baa</defined>!</def>
318
-
319
- <def tag="NestedStaticMerge">merge StaticMerge: <StaticMerge param/></def>
320
-
321
- <def tag="ParameterMerge">parameter merge: <StaticMerge><b param/></StaticMerge></def>
322
- END
323
- end
324
-
325
- it "should call template tags" do
326
- eval_with_templates("<T/>").should == "plain template"
327
- end
328
-
329
- it "should add attributes to static tags when merging" do
330
- eval_with_templates("<StaticMerge><b onclick='alert()'/></StaticMerge>").should ==
331
- '<p>a <b name="big" onclick="alert()">bold</b> word</p>'
332
- end
333
-
334
- it "should override attributes on static tags when merging" do
335
- eval_with_templates("<StaticMerge><b name='small'/></StaticMerge>").should ==
336
- '<p>a <b name="small">bold</b> word</p>'
337
- end
338
-
339
- it "should replace tag bodies on static tags when merging" do
340
- eval_with_templates('<StaticMerge><b>BOLD</b></StaticMerge>').should ==
341
- '<p>a <b name="big">BOLD</b> word</p>'
342
- end
343
-
344
- it "should add attributes to defined tags when merging" do
345
- eval_with_templates('<DefTagMerge><defined a="2"/></DefTagMerge>').should ==
346
- 'foo a is 2, b is 3, body is baa!'
347
- end
348
-
349
- it "should override attributes on defined tags when merging" do
350
- eval_with_templates('<DefTagMerge><defined b="2"/></DefTagMerge>').should ==
351
- 'foo a is , b is 2, body is baa!'
352
- end
353
-
354
- it "should replace tag bodies on defined tags when merging" do
355
- eval_with_templates('<DefTagMerge><defined>zip</defined></DefTagMerge>').should ==
356
- 'foo a is , b is 3, body is zip!'
357
- end
358
-
359
- it "should leave non-merged tags unchanged" do
360
- eval_with_templates('<StaticMerge></StaticMerge>').should ==
361
- '<p>a <b name="big">bold</b> word</p>'
362
- end
363
-
364
- it "should merge into static tags with no body" do
365
- eval_with_templates("<EmptyStaticMerge><img name='small'/></EmptyStaticMerge>").should ==
366
- '<img name="small" src="..." />'
367
- end
368
-
369
- it "should merge template parameters into nested templates" do
370
- eval_with_templates('<NestedStaticMerge><StaticMerge><b name="small"/></StaticMerge></NestedStaticMerge>').should ==
371
- 'merge StaticMerge: <p>a <b name="small">bold</b> word</p>'
372
- end
373
-
374
- it "should merge the body of template parameters into nested templates" do
375
- eval_with_templates('<NestedStaticMerge><StaticMerge><b>BOLD</b></StaticMerge></NestedStaticMerge>').should ==
376
- 'merge StaticMerge: <p>a <b name="big">BOLD</b> word</p>'
377
- end
378
-
379
- it "should allow param names to be defined dynamically" do
380
- eval_dryml('<def tag="T"><p param="& :a.to_s + :b.to_s"/></def>' +
381
- '<T><ab x="1"/></T>').should == '<p x="1" />'
382
- end
383
-
384
- it "should allow params to be defined on other params" do
385
- eval_with_templates('<ParameterMerge><b name="small">foo</b></ParameterMerge>').should ==
386
- 'parameter merge: <p>a <b name="small">foo</b> word</p>'
387
-
388
- end
389
-
390
- it "should allow parameter bodies to be restored with static tag params" do
391
- eval_with_templates("<StaticMerge><b>very <default_tagbody/></b></StaticMerge>").should ==
392
- '<p>a <b name="big">very bold</b> word</p>'
393
- end
394
-
395
- it "should allow parameter bodies to be restored with defined tag params" do
396
- eval_with_templates("<DefTagMerge><defined>hum<default_tagbody/></defined></DefTagMerge>").should ==
397
- 'foo a is , b is 3, body is humbaa!'
398
- end
399
-
400
-
401
-
402
- # --- Replacing Template Parameters --- #
403
-
404
- it "should allow template parameters to be replaced" do
405
- eval_with_templates('<StaticMerge><b replace>short</b></StaticMerge>').should ==
406
- '<p>a short word</p>'
407
- end
408
-
409
- it "should allow template parameters to be replaced and then re-instated" do
410
- eval_with_templates('<StaticMerge><b replace>short <b restore/></b></StaticMerge>').should ==
411
- '<p>a short <b name="big">bold</b> word</p>'
412
- end
413
-
414
- it "should allow template parameters to be replaced and then re-instated with different attributes" do
415
- eval_with_templates('<StaticMerge><b replace>short <b restore name="small"/></b></StaticMerge>').should ==
416
- '<p>a short <b name="small">bold</b> word</p>'
417
- end
418
-
419
- it "should allow template parameters to be replaced and then re-instated with a different tagbody" do
420
- eval_with_templates('<StaticMerge><b replace>short <b restore>big</b></b></StaticMerge>').should ==
421
- '<p>a short <b name="big">big</b> word</p>'
422
- end
423
-
424
- # --- Merge Params --- #
425
-
426
-
427
- it "should support merge_param on template calls" do
428
- tags = %(<def tag="Page"><h1 param='title'/><div param='footer'/></def>
429
- <def tag="MyPage"><Page merge_params><footer>the footer</footer></Page></def>)
430
-
431
- eval_dryml(tags + "<MyPage><title>Hi!</title></MyPage>").should == '<h1>Hi!</h1><div>the footer</div>'
432
- end
433
-
434
-
435
- # --- Polymorphic Tags --- #
436
-
437
- it "should allow tags to be selected based on types" do
438
- tags = %(<def tag="do"><tagbody/></def>
439
- <def tag="t" for="String">A string</def>
440
- <def tag="t" for="TrueClass">A boolean</def>)
441
-
442
- eval_dryml(tags + '<do with="&\'foo\'"><%= call_polymorphic_tag(:t) %></do>').should == "A string"
443
- eval_dryml(tags + '<do with="&false"><%= call_polymorphic_tag(:t) %></do>').should == "A boolean"
444
- end
445
-
446
- # --- The Context --- #
447
-
448
- def context_eval(context, src)
449
- eval_dryml(src, :context => context)
450
- end
451
-
452
- def a_user
453
- Struct.new(:name, :email).new("Tom", "tom@foo.net")
454
- end
455
-
456
- def show_tag
457
- '<def tag="show"><%= this %></def>'
458
- end
459
-
460
- it "should make the initial context available as `this`" do
461
- context_eval('hello', "<%= this %>").should == "hello"
462
- end
463
-
464
- it "should allow the context to be changed with the :<field-name> syntax" do
465
- context_eval(a_user, show_tag + '<show:name/>').should == "Tom"
466
- end
467
-
468
- it "should allow the :<field-name> to be ommitted from the close tag" do
469
- context_eval(a_user, show_tag + '<show:name></show:name>').should == "Tom"
470
- context_eval(a_user, show_tag + '<show:name></show>').should == "Tom"
471
- end
472
-
473
-
474
- it "should allow the context to be changed with a 'with' attribute" do
475
- eval_dryml(show_tag + %(<show with="&'hello'"/>)).should == 'hello'
476
- end
477
-
478
- it "should allow the context to be changed with a 'field' attribute" do
479
- context_eval(a_user, show_tag + '<show field="name"/>').should == "Tom"
480
- end
481
-
482
- it "should allow the context to be changed inside template parameters" do
483
- tags = %(<def tag="do"><tagbody/></def>
484
- <def tag="Template"><do:name><p param/></do></def>)
485
- context_eval(a_user, tags + '<Template><p><%= this %></p></Template>').should == '<p>Tom</p>'
486
- end
487
-
488
-
489
- # --- <set> --- #
490
-
491
- it "should provide <set> to create local variables" do
492
- eval_dryml("<set x='&1' y='&2'/><%= x + y %>").should == '3'
493
- end
494
-
495
- it 'should interpolate #{...} blocks in attributes of any tag' do
496
- tag = '<def tag="t" attrs="x"><%= x %></def>'
497
-
498
- eval_dryml(tag + "<t x='#{1+2}'/>").should == '3'
499
- eval_dryml(tag + "<t x='hey #{1+2} ho'/>").should == 'hey 3 ho'
500
-
501
- eval_dryml(tag + "<p class='#{1+2}'/>").should == "<p class='3'/>"
502
- eval_dryml(tag + "<p class='hey #{1+2} ho'/>").should == "<p class='hey 3 ho'/>"
503
- end
504
-
505
-
506
- # --- <set_scoped> --- #
507
-
508
- it "should support scoped variables" do
509
- tags =
510
- "<def tag='t1'><set_scoped x='ping'><tagbody/></set_scoped></def>" +
511
- "<def tag='t2'><set_scoped x='pong'><tagbody/></set_scoped></def>"
512
- eval_dryml(tags + "<t1><%= scope.x %></t1>").should == 'ping'
513
- eval_dryml(tags + "<t1><t2><%= scope.x %></t2> <%= scope.x %></t1>").should == 'pong ping'
514
- end
515
-
516
-
517
- # --- Taglibs --- #
518
-
519
- it "should import tags from taglibs with the <include> tag" do
520
- eval_dryml("<include src='taglibs/simple'/> <foo/>").should == "I am the foo tag"
521
- end
522
-
523
- it "should import tags from taglibs into a namespace with <include as/>" do
524
- proc { eval_dryml("<include src='taglibs/simple' as='a'/> <foo/>") }.should raise_error
525
- eval_dryml("<include src='taglibs/simple' as='a'/> <a.foo/>").should == "I am the foo tag"
526
- end
527
-
528
-
529
- # --- Control Attributes --- #
530
-
531
- it "should alow static tags to be conditional with the 'if' attribute" do
532
- eval_dryml("<p if='&false'/>").should == ""
533
- eval_dryml("<p if='&true'/>").should == "<p />"
534
-
535
- eval_dryml("<p if='&false'>hello</p>").should == ""
536
- eval_dryml("<p if='&true'>hello</p>").should == "<p>hello</p>"
537
- end
538
-
539
- it "should alow static tags to be repeated with the 'repeat' attribute" do
540
- eval_dryml('<img repeat="&[1,2,3]" src="#{this}" />').should ==
541
- '<img src="1" /><img src="2" /><img src="3" />'
542
-
543
- # Make sure <%= %> doesn't break
544
- eval_dryml('<img repeat="&[1,2,3]" src="<%= this %>" />').should ==
545
- '<img src="1" /><img src="2" /><img src="3" />'
546
- end
547
-
548
- it "should alow templates to be repeated with the 'repeat' attribute" do
549
- eval_dryml('<def tag="T"><%= this %></def><T repeat="&[1,2,3]"/>').should == '123'
550
- end
551
-
552
- it "should allow <else> to be used with the if attribute" do
553
- eval_dryml("<p if='&false'/><%= Hobo::Dryml.last_if %>").should == "false"
554
- end
555
-
556
-
557
- # --- Test Helpers --- #
558
-
559
- def prepare_template(src, options)
560
- options.reverse_merge!(:template_path => "TEST")
561
-
562
- Hobo::Dryml::Template.clear_build_cache
563
- @env = Class.new(Hobo::Dryml::TemplateEnvironment)
564
- template = Template.new(src, @env, options[:template_path])
565
-
566
- template.instance_variable_set("@builder", options[:builder]) if options[:builder]
567
- template
568
- end
569
-
570
-
571
- def eval_dryml(src, options={})
572
- options.reverse_merge!(:locals => {}, :implicit_imports => [])
573
-
574
- template = prepare_template(src, options)
575
- template.compile(options[:locals].keys, options[:implicit_imports])
576
- new_renderer.render_page(options[:context], options[:locals]).strip
577
- end
578
-
579
- def compile_dryml(src, options={})
580
- template = prepare_template(src, options)
581
- CompiledDryml.new(template.process_src)
582
- end
583
-
584
- def new_renderer
585
- @env.new("test-view", nil)
586
- end
587
-
588
- def compile_in_template(src)
589
- builder = mock("builder", :null_object => true)
590
- def_src = nil
591
- builder.should_receive(:add_build_instruction) do |type, args|
592
- def_src = args[:src]
593
- end
594
- compile_dryml("<def tag='MyTemplate'>#{src}</def>", :builder => builder)
595
-
596
- # get rid of first and last scriptlets - they're to do with the method declaration
597
- def_src.to_s.sub(/^\<\%.*?\%\>/, "").sub(/<% _erbout; end; end %><% _register_tag_attrs.*$/, "")
598
- end
599
-
600
- def compile_def(src)
601
- builder = mock("builder", :null_object => true)
602
- def_src = nil
603
- builder.should_receive(:add_build_instruction) do |type, args|
604
- def_src = args[:src]
605
- end
606
- compile_dryml(src, :builder => builder)
607
-
608
- def_src.sub(/<% _register_tag_attrs.*/, "")
609
- end
610
-
611
- end
612
-
613
- class CompiledDryml < String
614
-
615
- def ==(other)
616
- self.to_s.gsub(/\s+/, ' ').strip == other.gsub(/\s+/, ' ').strip
617
- end
618
-
619
- end
620
-
621
-
622
- module Spec
623
- module Matchers
624
-
625
- class BeDomEqualTo #:nodoc:
626
- def initialize(expected)
627
- @expected = expected
628
- end
629
-
630
- def matches?(actual)
631
- @actual = actual
632
- expected_dom = HTML::Document.new(@expected).root
633
- actual_dom = HTML::Document.new(@actual).root
634
- expected_dom == actual_dom
635
- end
636
-
637
- def failure_message
638
- "#{@expected}\nexpected to be == (by DOM) to\n#{@actual}"
639
- end
640
-
641
- def description
642
- "be DOM equal to\n#{@expected}"
643
- end
644
- end
645
-
646
- def be_dom_equal_to(expected)
647
- Matchers::BeDomEqualTo.new(expected)
648
- end
649
- end
650
- end