hobo 0.6.1 → 0.6.2

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