hobo 0.5.3 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/bin/hobo +18 -4
  2. data/hobo_files/plugin/CHANGES.txt +511 -0
  3. data/hobo_files/plugin/README +8 -3
  4. data/hobo_files/plugin/Rakefile +81 -0
  5. data/hobo_files/plugin/generators/hobo/hobo_generator.rb +4 -4
  6. data/hobo_files/plugin/generators/hobo/templates/guest.rb +1 -1
  7. data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +1 -1
  8. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +16 -22
  9. data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +4 -6
  10. data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +6 -5
  11. data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +4 -6
  12. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +237 -0
  13. data/hobo_files/plugin/generators/hobo_migration/templates/migration.rb +9 -0
  14. data/hobo_files/plugin/generators/hobo_model/USAGE +2 -3
  15. data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +1 -14
  16. data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +1 -6
  17. data/hobo_files/plugin/generators/hobo_model/templates/model.rb +10 -4
  18. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +7 -6
  19. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_base.css +68 -0
  20. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.css +93 -0
  21. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +11 -6
  22. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/plus.png +0 -0
  23. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +24 -14
  24. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +28 -44
  25. data/hobo_files/plugin/generators/hobo_user_model/USAGE +2 -12
  26. data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +1 -14
  27. data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +0 -6
  28. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +8 -1
  29. data/hobo_files/plugin/init.rb +6 -2
  30. data/hobo_files/plugin/lib/active_record/has_many_association.rb +23 -12
  31. data/hobo_files/plugin/lib/extensions.rb +134 -40
  32. data/hobo_files/plugin/lib/extensions/test_case.rb +0 -1
  33. data/hobo_files/plugin/lib/hobo.rb +77 -46
  34. data/hobo_files/plugin/lib/hobo/authenticated_user.rb +24 -2
  35. data/hobo_files/plugin/lib/hobo/authentication_support.rb +2 -1
  36. data/hobo_files/plugin/lib/hobo/controller.rb +35 -12
  37. data/hobo_files/plugin/lib/hobo/define_tags.rb +4 -4
  38. data/hobo_files/plugin/lib/hobo/dryml.rb +33 -51
  39. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +47 -34
  40. data/hobo_files/plugin/lib/hobo/dryml/scoped_variables.rb +37 -0
  41. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +27 -5
  42. data/hobo_files/plugin/lib/hobo/dryml/template.rb +545 -302
  43. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +305 -135
  44. data/hobo_files/plugin/lib/hobo/email_address.rb +5 -0
  45. data/hobo_files/plugin/lib/hobo/field_spec.rb +66 -0
  46. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +325 -0
  47. data/hobo_files/plugin/lib/hobo/html_string.rb +2 -0
  48. data/hobo_files/plugin/lib/hobo/lazy_hash.rb +13 -1
  49. data/hobo_files/plugin/lib/hobo/markdown_string.rb +3 -1
  50. data/hobo_files/plugin/lib/hobo/model.rb +185 -66
  51. data/hobo_files/plugin/lib/hobo/model_controller.rb +56 -49
  52. data/hobo_files/plugin/lib/hobo/password_string.rb +2 -0
  53. data/hobo_files/plugin/lib/hobo/plugins.rb +75 -0
  54. data/hobo_files/plugin/lib/hobo/rapid_helper.rb +98 -0
  55. data/hobo_files/plugin/lib/hobo/static_tags +0 -3
  56. data/hobo_files/plugin/lib/hobo/textile_string.rb +11 -1
  57. data/hobo_files/plugin/lib/hobo/undefined.rb +1 -1
  58. data/hobo_files/plugin/lib/rexml.rb +166 -75
  59. data/hobo_files/plugin/spec/fixtures/users.yml +9 -0
  60. data/hobo_files/plugin/spec/spec.opts +6 -0
  61. data/hobo_files/plugin/spec/spec_helper.rb +28 -0
  62. data/hobo_files/plugin/spec/unit/hobo/dryml/template_spec.rb +650 -0
  63. data/hobo_files/plugin/tags/core.dryml +58 -4
  64. data/hobo_files/plugin/tags/rapid.dryml +289 -135
  65. data/hobo_files/plugin/tags/rapid_document_tags.dryml +49 -0
  66. data/hobo_files/plugin/tags/rapid_editing.dryml +92 -69
  67. data/hobo_files/plugin/tags/rapid_forms.dryml +242 -0
  68. data/hobo_files/plugin/tags/rapid_navigation.dryml +65 -65
  69. data/hobo_files/plugin/tags/rapid_pages.dryml +197 -124
  70. data/hobo_files/plugin/tags/rapid_support.dryml +23 -0
  71. metadata +29 -22
  72. data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +0 -13
  73. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +0 -11
  74. data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +0 -15
  75. data/hobo_files/plugin/lib/hobo/HtmlString +0 -3
  76. data/hobo_files/plugin/lib/hobo/controller_helpers.rb +0 -135
  77. data/hobo_files/plugin/lib/hobo/core.rb +0 -475
  78. data/hobo_files/plugin/lib/hobo/rapid.rb +0 -447
  79. data/hobo_files/plugin/test/hobo_dryml_template_test.rb +0 -7
  80. data/hobo_files/plugin/test/hobo_test.rb +0 -7
@@ -1,447 +0,0 @@
1
- module Hobo::Rapid
2
-
3
- include Hobo::DefineTags
4
-
5
- TYPE_NAMES = {
6
- Hobo::HtmlString => :html,
7
- Hobo::Text => :textarea,
8
- TrueClass => :boolean,
9
- FalseClass => :boolean,
10
- Date => :date,
11
- Time => :datetime,
12
- Hobo::PasswordString => :password_string,
13
- Fixnum => :integer,
14
- BigDecimal => :integer,
15
- Float => :float,
16
- String => :string
17
- }
18
-
19
- def options_for_hobo_ajax(options)
20
- js_options = build_callbacks(options)
21
-
22
- js_options['asynchronous'] = false if options[:type] == :synchronous
23
- js_options['method'] = method_option_to_s(options[:method]) if options[:method]
24
- js_options['evalScripts'] = false if options[:script] == false
25
- js_options['form'] = options[:form] if options[:form]
26
- js_options['params'] = make_params_js(options[:params]) if options[:params]
27
- js_options['resultUpdate'] = js_result_updates(options[:result_update]) if options[:result_update]
28
- js_options['resetForm'] = false if options[:reset_form] == false
29
- js_options['refocusForm'] = false if options[:refocus_form] == false
30
-
31
- js_options.empty? ? nil : options_for_javascript(js_options)
32
- end
33
-
34
-
35
- def js_updates(updates)
36
- return '[]' unless updates
37
- updates = [updates] unless updates.is_a? Array
38
- '[' + comma_split(updates).map{|u| js_str(u)}.join(', ') + ']'
39
- end
40
-
41
-
42
- def js_result_updates(updates)
43
- return '[]' unless updates
44
- updates = [updates] unless updates.is_a? Array
45
- pairs = comma_split(updates).omap{split(/\s*=\s*/)}
46
- '[' + pairs.map{|p| "{id: #{js_str(p[0])}, result: #{js_str(p[1])}}"}.join(", ") + ']'
47
- end
48
-
49
-
50
- def ajax_updater(url_or_form, message, update, options={})
51
- options ||= {}
52
- target = if url_or_form == :post_form
53
- target = "this"
54
- else
55
- js_str(url_or_form)
56
- end
57
- js_options = options_for_hobo_ajax(options)
58
- args = [target, js_str(message || "..."), js_updates(update), js_options].compact
59
-
60
- confirm = options.delete(:confirm)
61
-
62
- func = "Hobo.ajaxRequest(#{args * ', '})"
63
- if confirm
64
- "if (confirm(#{js_str(confirm)})) { #{func} }"
65
- else
66
- func
67
- end
68
- end
69
-
70
-
71
- def a_or_an(word)
72
- if word =~ /^[aeiouh]/
73
- "an #{word}"
74
- else
75
- "a #{word}"
76
- end
77
- end
78
-
79
-
80
- def no_break(s)
81
- s = new_context { yield } if block_given?
82
- s.gsub(' ', ' ')
83
- end
84
-
85
-
86
- def_tag :if_current_user_in do
87
- if_(:q => current_user_in?(this)) { tagbody.call }
88
- end
89
-
90
-
91
- def_tag :edit, :in_place do
92
- if can_view_this?
93
- if not can_edit_this?
94
- show
95
- elsif this_parent.new_record? or in_place == false
96
- form_field(options)
97
- else
98
- editor(options)
99
- end
100
- end
101
- end
102
-
103
-
104
- def type_name(klass)
105
- TYPE_NAMES[klass]
106
- end
107
-
108
-
109
- def_tag :form_field do
110
- raise HoboError.new("Not allowed to edit") unless can_edit_this?
111
- if this_type.respond_to?(:macro)
112
- if this_type.macro == :belongs_to
113
- belongs_to_field(options)
114
- elsif this_type.macro == :has_many
115
- has_many_field(options)
116
- end
117
-
118
- else
119
- tag = type_name(this_type).to_s + "_field"
120
- if respond_to?(tag)
121
- options[:name] ||= param_name_for_this
122
- tag_src = send(tag, options)
123
- if this_parent.errors[this_field]
124
- "<div class='field_with_errors'>#{tag_src}</div>"
125
- else
126
- tag_src
127
- end
128
- else
129
- raise HoboError, ("No form field tag for #{this_field}:#{this_type} (this=#{this.inspect})")
130
- end
131
- end
132
- end
133
-
134
- def_tag :has_many_field do
135
- raise NotImplementedError, "form field for has_many associations not implemented"
136
- end
137
-
138
- def_tag :belongs_to_field do
139
- belongs_to_menu_field(options)
140
- end
141
-
142
- def_tag :textarea_field, :name do
143
- text_area_tag(name, this, options)
144
- end
145
-
146
-
147
- def_tag :boolean_field, :name do
148
- check_box_tag(name, '1', this, options)
149
- end
150
-
151
- def_tag :password_string_field, :name do
152
- password_field_tag(name, this)
153
- end
154
-
155
- def_tag :html_field, :name do
156
- text_area_tag(name, this, add_classes(options, :tiny_mce))
157
- end
158
-
159
- def_tag :date_field do
160
- select_date(this || Time.now, :prefix => param_name_for_this)
161
- end
162
-
163
- def_tag :datetime_field do
164
- select_datetime(this || Time.now, :prefix => param_name_for_this)
165
- end
166
-
167
- def_tag :integer_field, :name do
168
- text_field_tag(name, this, options)
169
- end
170
-
171
- def_tag :float_field, :name do
172
- text_field_tag(name, this, options)
173
- end
174
-
175
- def_tag :string_field, :name do
176
- text_field_tag(name, this, options)
177
- end
178
-
179
- def_tag :editor do
180
- raise HoboError.new("Not allowed to edit") unless can_edit_this?
181
-
182
- if this_type.respond_to?(:macro)
183
- if this_type.macro == :belongs_to
184
- belongs_to_editor(options)
185
- else
186
- has_many_editor(options)
187
- end
188
- else
189
- tag = type_name(this_type).to_s + "_editor"
190
- if respond_to?(tag)
191
- send(tag, options)
192
- else
193
- raise HoboError.new("<editor> not implemented for #{this.class.name}\##{this_field} " +
194
- "(#{this.inspect}:#{this_type})")
195
- end
196
- end
197
- end
198
-
199
-
200
- def_tag :has_many_editor do
201
- # TODO: Implement
202
- object_link(options)
203
- end
204
-
205
-
206
- def in_place_editor(kind, tag, options)
207
- opts = add_classes(options, kind, editor_class).merge(:hobo_model_id => this_field_dom_id)
208
-
209
- update = opts.delete(:update)
210
- blank_message = opts.delete(:blank_message) || "(click to edit)"
211
-
212
- display = show(:no_span => true)
213
- opts[:hobo_blank_message] = blank_message
214
- display = blank_message if display.blank?
215
- opts[:hobo_update] = update if update
216
- content_tag(tag, display, opts)
217
- end
218
-
219
-
220
- def_tag :string_editor do
221
- in_place_editor "in_place_textfield_bhv", :span, options
222
- end
223
-
224
- def_tag :textarea_editor do
225
- in_place_editor "in_place_textarea_bhv", :div, options
226
- end
227
-
228
- def_tag :html_editor do
229
- in_place_editor "in_place_html_textarea_bhv", :div, options
230
- end
231
-
232
- def_tag :belongs_to_editor do
233
- belongs_to_menu_editor(options)
234
- end
235
-
236
- def_tag :datetime_editor do
237
- string_editor(options)
238
- end
239
-
240
- def_tag :date_editor do
241
- string_editor(options)
242
- end
243
-
244
- def_tag :integer_editor do
245
- in_place_editor "in_place_textfield_bhv", :span, options
246
- end
247
-
248
- def_tag :float_editor do
249
- in_place_editor "in_place_textfield_bhv", :span, options
250
- end
251
-
252
- def_tag :password_string_editor do
253
- raise HoboError, "passwords cannot be edited in place"
254
- end
255
-
256
- def_tag :boolean_editor do
257
- boolean_checkbox_editor(options)
258
- end
259
-
260
-
261
- AJAX_ATTRS = [:before, :success, :failure, :complete, :type, :method,
262
- :script, :form, :params, :confirm,
263
- :reset_form, :refocus_form]
264
-
265
-
266
- def_tag :update_button, :label, :message, :attrs, :update, :params do
267
- raise HoboError.new("no update specified") unless update
268
- message2 = message || label
269
- func = ajax_updater(object_url(this), message2, update,
270
- :params => { this.class.name.underscore => attrs }.merge(params || {}),
271
- :method => :put)
272
- tag :input, add_classes(options.merge(:type =>'button', :onclick => func, :value => label),
273
- "button_input update_button update_#{this.class.name.underscore}_button")
274
- end
275
-
276
-
277
- def_tag :delete_button, :label, :message, :update, :ajax, :else, :image, :confirm, :fade do
278
- fade2 = fade.nil? ? true : fade
279
- if can_delete?(this)
280
- opts = options.merge(if image
281
- { :type => "image", :src => "#{urlb}/images/#{image}" }
282
- else
283
- { :type => "button" }
284
- end)
285
- label2 = label || "Remove"
286
- confirm2 = confirm || "Are you sure?"
287
-
288
- add_classes!(opts,
289
- image ? "image_button_input" : "button_input",
290
- "delete_button delete_#{this.class.name.underscore}_button")
291
- url = object_url(this, "destroy")
292
- if ajax == false
293
- opts[:confirm] = confirm2
294
- button_to(label2, url, opts)
295
- else
296
- opts[:value] = label2
297
- opts[:onclick] = "Hobo.removeButton(this, '#{url}', #{js_updates(update)}, #{fade2 ? 'true' : 'false'})"
298
- tag(:input, opts)
299
- end
300
- else
301
- else_
302
- end
303
- end
304
-
305
-
306
- def_tag :create_button, :model, :update, :attrs, :label, :message, :else do
307
- raise HoboError.new("no update specified") unless update
308
- params = attrs || {}
309
- if model
310
- new = (model.is_a?(String) ? model.constantize : model).new(params)
311
- else
312
- raise HoboError.new("invalid context for <create_button>") unless Hobo.simple_has_many_association?(this)
313
- params[this.proxy_reflection.primary_key_name] = this.proxy_owner.id
314
- new = this.new(params)
315
- end
316
- if can_create?(new)
317
- label2 = label || "New #{new.class.name.titleize}"
318
- message2 = message || label2
319
- class_name = new.class.name.underscore
320
- func = ajax_updater(object_url(new.class), message2, update,
321
- ({:params => { class_name => params }} unless params.empty?))
322
- tag :input, add_classes(options.merge(:type =>'button', :onclick => func, :value => label2),
323
- "button_input create_button create_#{class_name}_button")
324
- else
325
- else_
326
- end
327
- end
328
-
329
-
330
- def_tag :remote_method_button, :method, :update, :result_update, :params, :label, :message do
331
- ajax_options, html_options = options.partition_hash(AJAX_ATTRS)
332
-
333
- message2 = message || method.titleize
334
- func = ajax_updater(object_url(this) + "/#{method}", message2, update,
335
- ajax_options.merge(:params => params, :result_update => result_update))
336
- html_options.update(:type =>'button', :onclick => "var e = this; " + func, :value => label)
337
- tag(:input, add_classes(html_options, "button_input remote_method_button #{method}_button"))
338
- end
339
-
340
-
341
- def_tag :hobo_rapid_javascripts, :tiny_mce do
342
- res = javascript_include_tag("hobo_rapid")
343
- res += "<script>"
344
- unless Hobo.all_controllers.empty?
345
- res += "var controllerNames = {" +
346
- Hobo.all_controllers.map {|c| "#{c.singularize}: '#{c}'"}.join(', ') +
347
- "}; "
348
- end
349
- res += "urlBase = '#{urlb}'; hoboPartPage = '#{view_name}'</script>"
350
-
351
- if tiny_mce
352
- res += javascript_include_tag("tiny_mce/tiny_mce_src") + %{
353
- <script type="text/javascript">
354
- tinyMCE.init({ mode: "textareas", editor_selector: "tiny_mce",
355
- plugins: 'save',
356
- theme_advanced_buttons1 : "bold, italic, separator, " +
357
- "bullist, outdent, indent, separator, " +
358
- "undo, redo, separator, link, unlink",
359
- theme_advanced_buttons2 : "",
360
- theme_advanced_buttons3 : ""
361
- });
362
- </script>}
363
- end
364
- res
365
- end
366
-
367
-
368
- def_tag :object_form, :message, :update, :hidden_fields, :url do
369
- ajax_options, html_options = options.partition_hash(AJAX_ATTRS)
370
-
371
- url2 = url || object_url(this)
372
- if update
373
- # add an onsubmit to convert to an ajax form if `update` is given
374
- function = ajax_updater(:post_form, message, update, ajax_options)
375
- html_options[:onsubmit] = [html_options[:onsubmit],
376
- "#{function}; return false;"].compact.join("; ")
377
- end
378
-
379
- body, field_names = with_form_context{ tagbody.call }
380
- body = body.to_s
381
-
382
- hiddens = case hidden_fields
383
- when nil
384
- []
385
- when '*'
386
- this.class.column_names - ['type']
387
- else
388
- comma_split(hidden_fields)
389
- end
390
- pname = this.class.name.underscore
391
- hidden_tags = hiddens.map do |h|
392
- val = this.send(h)
393
- name = "#{pname}[#{h}]"
394
- hidden_field_tag(name, val.to_s) if val and name.not_in?(field_names)
395
- end
396
- hidden_tags << hidden_field_tag("_method", "PUT") unless this.respond_to?(:new_record?) and this.new_record?
397
-
398
- html_options[:method] = "post"
399
- body_with_hiddens = hidden_tags.compact.join("\n") + body
400
-
401
- form_class = this.new_record? ? "new_#{this.class.name.underscore}" : this.class.name.underscore
402
-
403
- content_tag("form", body_with_hiddens, add_classes(html_options, form_class).merge(:action => url2))
404
- end
405
-
406
-
407
- def_tag :create_form, :model, :in, :update, :message, :hidden_fields do
408
- hiddens = hidden_fields
409
- if model
410
- obj = (model.is_a?(String) ? model.constantize : model).new
411
- else
412
- raise HoboError.new("cannot create object in #{in_.inspect}") unless this.is_a? Array
413
- obj = this.new
414
- refl = this.proxy_reflection
415
- if refl.macro == :has_many and !refl.through_reflection
416
- hiddens ||= [refl.primary_key_name]
417
- end
418
- end
419
- m = message || "New #{obj.class.name.titleize}"
420
- options = add_classes(options, "create_#{obj.class.underscore.name}_form")
421
- object_form(obj, options.merge(:message => m, :update => update, :hidden_fields => hiddens)) do
422
- tagbody.call
423
- end
424
- end
425
-
426
- def_tag :remote_method_form, :method, :message, :update, :result_update do
427
- ajax_options, html_options = options.partition_hash(AJAX_ATTRS)
428
-
429
- url = object_url(this, method)
430
- if update || result_update || !ajax_options.empty?
431
- # add an onsubmit to convert to an ajax form
432
-
433
- function = ajax_updater(:post_form, message, update, ajax_options.merge(:result_update => result_update))
434
- html_options[:onsubmit] = [html_options[:onsubmit],
435
- "var e = this; #{function}; return false;"].compact.join("; ")
436
- end
437
-
438
- add_classes!(html_options, "#{this.class.name.underscore}_#{method}_form")
439
- html_options[:method] = "post"
440
- content_tag("form", tagbody.call, html_options.merge(:action => url))
441
- end
442
-
443
- def editor_class
444
- "#{this_parent.class.name.underscore}_#{this_field}_editor"
445
- end
446
-
447
- end
@@ -1,7 +0,0 @@
1
- require 'test/unit'
2
-
3
- class HoboDrymlTemplateTest < Test::Unit::TestCase
4
- # Replace this with your real tests.
5
- def test_this_plugin
6
- end
7
- end