hobo 0.6.4 → 0.7.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.
Files changed (71) hide show
  1. data/bin/hobo +4 -6
  2. data/hobo_files/plugin/CHANGES.txt +170 -0
  3. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +9 -9
  4. data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +9 -9
  5. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +7 -2
  6. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +4 -4
  7. data/hobo_files/plugin/generators/hobo_rapid/templates/{hobo_rapid.css → hobo-rapid.css} +0 -0
  8. data/hobo_files/plugin/generators/hobo_rapid/templates/{hobo_rapid.js → hobo-rapid.js} +66 -47
  9. data/hobo_files/plugin/generators/hobo_rapid/templates/lowpro.js +130 -44
  10. data/hobo_files/plugin/generators/hobo_rapid/templates/{hobo_base.css → reset.css} +0 -5
  11. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/pencil.png +0 -0
  12. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/small_close.png +0 -0
  13. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +45 -0
  14. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid_ui.css +167 -0
  15. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/views/application.dryml +10 -0
  16. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_bodytop.gif → bkg-bodytop.gif} +0 -0
  17. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_01.gif → bkg-corner-01.gif} +0 -0
  18. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_02.gif → bkg-corner-02.gif} +0 -0
  19. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_03.gif → bkg-corner-03.gif} +0 -0
  20. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_corner_04.gif → bkg-corner-04.gif} +0 -0
  21. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_bottom.gif → bkg-shadow-bottom.gif} +0 -0
  22. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_left.gif → bkg-shadow-left.gif} +0 -0
  23. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_right.gif → bkg-shadow-right.gif} +0 -0
  24. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{bkg_shadow_top.gif → bkg-shadow-top.gif} +0 -0
  25. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_blue.gif → header-blue.gif} +0 -0
  26. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_dblue.gif → header-dblue.gif} +0 -0
  27. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_green.gif → header-green.gif} +0 -0
  28. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_purple.gif → header-purple.gif} +0 -0
  29. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{header_red.gif → header-red.gif} +0 -0
  30. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_dblue.gif → txt-list-img-dblue.gif} +0 -0
  31. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_green.gif → txt-list-img-green.gif} +0 -0
  32. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_purple.gif → txt-list-img-purple.gif} +0 -0
  33. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{txt_list_img_red.gif → txt-list-img-red.gif} +0 -0
  34. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_01.gif → window-corner-01.gif} +0 -0
  35. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_02.gif → window-corner-02.gif} +0 -0
  36. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_03.gif → window-corner-03.gif} +0 -0
  37. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_corner_04.gif → window-corner-04.gif} +0 -0
  38. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_bottom.gif → window-shadow-bottom.gif} +0 -0
  39. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_left.gif → window-shadow-left.gif} +0 -0
  40. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_right.gif → window-shadow-right.gif} +0 -0
  41. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/{window_shadow_top.gif → window-shadow-top.gif} +0 -0
  42. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +69 -69
  43. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +39 -53
  44. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +1 -1
  45. data/hobo_files/plugin/lib/extensions.rb +0 -16
  46. data/hobo_files/plugin/lib/hobo/dryml/part_context.rb +1 -1
  47. data/hobo_files/plugin/lib/hobo/dryml/tag_parameters.rb +35 -0
  48. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +2 -2
  49. data/hobo_files/plugin/lib/hobo/dryml/template.rb +165 -236
  50. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +158 -123
  51. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +15 -4
  52. data/hobo_files/plugin/lib/hobo/model.rb +30 -11
  53. data/hobo_files/plugin/lib/hobo/model_controller.rb +13 -9
  54. data/hobo_files/plugin/lib/hobo/model_router.rb +27 -7
  55. data/hobo_files/plugin/lib/hobo/static_tags +0 -2
  56. data/hobo_files/plugin/lib/hobo/user.rb +3 -3
  57. data/hobo_files/plugin/lib/rexml.rb +10 -3
  58. data/hobo_files/plugin/tags/core.dryml +11 -16
  59. data/hobo_files/plugin/tags/rapid.dryml +147 -110
  60. data/hobo_files/plugin/tags/rapid_document_tags.dryml +22 -20
  61. data/hobo_files/plugin/tags/rapid_editing.dryml +41 -41
  62. data/hobo_files/plugin/tags/rapid_forms.dryml +51 -49
  63. data/hobo_files/plugin/tags/rapid_navigation.dryml +34 -34
  64. data/hobo_files/plugin/tags/rapid_pages.dryml +174 -174
  65. data/hobo_files/plugin/tags/rapid_plus.dryml +19 -19
  66. data/hobo_files/plugin/tags/rapid_support.dryml +5 -5
  67. data/hobo_files/plugin/tasks/dump_fixtures.rake +62 -53
  68. data/hobo_files/plugin/tasks/fix_dryml.rake +144 -0
  69. data/hobo_files/plugin/tasks/hobo_tasks.rake +0 -4
  70. metadata +43 -32
  71. data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +0 -9
@@ -19,7 +19,7 @@ module Hobo::Dryml
19
19
  @tag_attrs ||= {}
20
20
  end
21
21
 
22
- alias_method :_alias_tag_chain, :alias_tag_chain
22
+ alias_method :delayed_alias_method_chain, :alias_method_chain
23
23
 
24
24
  end
25
25
 
@@ -64,7 +64,7 @@ module Hobo::Dryml
64
64
 
65
65
 
66
66
  def add_classes!(attributes, *classes)
67
- classes = classes.flatten.select{|x|x}.every(:to_s)
67
+ classes = classes.flatten.select{|x|x}.map{|x| x.to_s.dasherize}
68
68
  current = attributes[:class]
69
69
  attributes[:class] = (current ? current.split + classes : classes).uniq.join(' ')
70
70
  attributes
@@ -161,7 +161,6 @@ module Hobo::Dryml
161
161
  end
162
162
  end
163
163
  end
164
- alias_method :find_polymorphic_template, :find_polymorphic_tag
165
164
 
166
165
 
167
166
  def repeat_attribute(array, &b)
@@ -236,30 +235,15 @@ module Hobo::Dryml
236
235
  end
237
236
 
238
237
 
239
- def _tag_context(options, tagbody_proc)
240
- tagbody = tagbody_proc && proc do |*args|
241
- res = ''
242
-
243
- block_options, default_tagbody = args
244
- block_with = block_options && block_options[:with]
245
- if block_options && block_options.has_key?(:field)
246
- new_field_context(block_options[:field], block_with) { res = tagbody_proc.call(default_tagbody) }
247
- elsif block_options && block_options.has_key?(:with)
248
- new_object_context(block_with) { res = tagbody_proc.call(default_tagbody) }
249
- else
250
- new_context { res = tagbody_proc.call(default_tagbody) }
251
- end
252
- res
253
- end
238
+ def _tag_context(attributes)
239
+ with = attributes[:with] == "page" ? @this : attributes[:with]
254
240
 
255
- with = options[:with] == "page" ? @this : options[:with]
256
-
257
- if options.has_key?(:field)
258
- new_field_context(options[:field], with) { yield tagbody }
259
- elsif options.has_key?(:with)
260
- new_object_context(with) { yield tagbody }
241
+ if attributes.has_key?(:field)
242
+ new_field_context(attributes[:field], with) { yield }
243
+ elsif attributes.has_key?(:with)
244
+ new_object_context(with) { yield }
261
245
  else
262
- new_context { yield tagbody }
246
+ new_context { yield }
263
247
  end
264
248
  end
265
249
 
@@ -286,7 +270,7 @@ module Hobo::Dryml
286
270
  attributes.delete(:with)
287
271
  attributes.delete(:field)
288
272
 
289
- # positional arguments never appear in the attributes hash
273
+ # declared attributes don't appear in the attributes hash
290
274
  stripped_attributes = HashWithIndifferentAccess.new.update(attributes)
291
275
  locals.each {|a| stripped_attributes.delete(a.to_sym) }
292
276
 
@@ -295,89 +279,100 @@ module Hobo::Dryml
295
279
  end
296
280
 
297
281
 
298
- def do_tagbody(tagbody, attributes, default_tagbody)
299
- res = if tagbody
300
- tagbody.call(attributes, default_tagbody)
282
+ def call_tag_parameter_with_default_content(the_tag, attributes, default_content, overriding_content_proc)
283
+ if the_tag.is_a?(String, Symbol) && the_tag.to_s.in?(Hobo.static_tags)
284
+ body = if overriding_content_proc
285
+ new_context { overriding_content_proc.call(proc { default_content._?.call(nil) }) }
286
+ elsif default_content
287
+ new_context { default_content.call(nil) }
288
+ else
289
+ nil
290
+ end
291
+ element(the_tag, attributes, body)
292
+ else
293
+ d = if overriding_content_proc
294
+ proc { |default| overriding_content_proc.call(proc { default_content._?.call(default) }) }
301
295
  else
302
- default_tagbody ? new_context { default_tagbody.call } : ""
296
+ proc { |default| default_content._?.call(default) }
303
297
  end
304
- Hobo::Dryml.last_if = !!tagbody
305
- res
298
+ send(the_tag, attributes, { :default => d })
299
+ end
306
300
  end
307
301
 
308
302
 
309
- def call_block_tag_parameter(the_tag, attributes, overriding_proc, &default_tagbody)
310
- if overriding_proc && overriding_proc.arity == 1
311
- # This is a 'replace' parameter
303
+ def call_tag_parameter(the_tag, attributes, parameters, caller_parameters, param_name)
304
+ overriding_proc = caller_parameters[param_name]
305
+
306
+ if param_name == :default && overriding_proc
307
+ # :default content is handled specially
308
+
309
+ call_tag_parameter_with_default_content(the_tag, attributes, parameters[:default], overriding_proc)
312
310
 
313
- template_default = proc do |attrs, body_block|
314
- tagbody_proc = body_block && proc {|_| new_context { body_block.call(default_tagbody) } }
315
- call_block_tag_parameter(the_tag, attributes, proc { attrs.update(:tagbody => tagbody_proc) }, &default_tagbody)
311
+ elsif overriding_proc && overriding_proc.arity == 1
312
+ # The caller is replacing this parameter. Don't call the tag
313
+ # at all, just the overriding proc, but pass the restorable
314
+ # tag as a parameter to the overriding proc
315
+
316
+ tag_restore = proc do |restore_attrs, restore_params|
317
+ # Call the replaced tag with the attributes and parameters
318
+ # as given in the original tag definition, and with the
319
+ # specialisation given on the 'restore' call
320
+ override_and_call_tag(the_tag, attributes, parameters, restore_attrs, restore_params)
316
321
  end
317
- overriding_proc.call(template_default)
322
+ overriding_proc.call(tag_restore)
323
+
318
324
  else
319
- if overriding_proc
320
- overriding_attributes = overriding_proc.call
321
- overriding_tagbody = overriding_attributes.delete(:tagbody)
322
- attributes = merge_attrs(attributes, overriding_attributes)
323
- end
325
+ overriding_attributes, overriding_parameters = overriding_proc._?.call
326
+ override_and_call_tag(the_tag, attributes, parameters, overriding_attributes, overriding_parameters)
327
+ end
328
+ end
329
+
330
+
331
+ def override_and_call_tag(the_tag, general_attributes, general_parameters, overriding_attributes, overriding_parameters)
332
+ attributes = overriding_attributes ? merge_attrs(general_attributes, overriding_attributes) : general_attributes
333
+ if overriding_parameters
334
+ overriding_default_content = overriding_parameters.delete(:default)
335
+ parameters = general_parameters.merge(overriding_parameters)
336
+ else
337
+ parameters = general_parameters
338
+ end
339
+
340
+ default_content = parameters[:default]
324
341
 
325
- if the_tag.is_a?(String, Symbol) && the_tag.to_s.in?(Hobo.static_tags)
326
- body = if overriding_tagbody
327
- new_context { overriding_tagbody.call(proc { default_tagbody.call(nil) }) }
328
- elsif default_tagbody
329
- new_context { default_tagbody.call(nil) }
330
- else
331
- nil
332
- end
333
- if body.blank?
334
- tag(the_tag, attributes)
335
- else
336
- content_tag(the_tag, body, attributes)
337
- end
338
- else
339
- if the_tag.is_a?(String, Symbol)
340
- body = proc do |default|
341
- if overriding_tagbody
342
- overriding_tagbody.call(proc { default_tagbody ? default_tagbody.call(default) : "" })
343
- else
344
- default_tagbody ? default_tagbody.call(default) : ""
345
- end
342
+ if the_tag.is_a?(String, Symbol) && the_tag.to_s.in?(Hobo.static_tags)
343
+ body = if overriding_default_content
344
+ new_context { overriding_default_content.call(proc { default_content._?.call(nil) }) }
345
+ elsif default_content
346
+ new_context { default_content.call(nil) }
347
+ else
348
+ nil
349
+ end
350
+ element(the_tag, attributes, body)
351
+ else
352
+ d = if overriding_default_content
353
+ proc { |default| overriding_default_content.call(proc { default_content._?.call(default) }) }
354
+ else
355
+ proc { |default| default_content._?.call(default) }
346
356
  end
347
-
348
- send(the_tag, attributes, &body)
349
- else
350
- # It's a proc - a template default
351
- the_tag.call(attributes, overriding_tagbody || default_tagbody)
352
- end
353
- end
354
- end
355
- end
356
-
357
- def call_template_parameter(the_template, attributes, template_procs, overriding_proc)
358
- if overriding_proc && overriding_proc.arity == 1
359
- # It's a replace parameter
357
+ parameters = parameters.merge(:default => d)
360
358
 
361
- template_default = proc do |attributes, parameters|
362
- call_template_parameter(the_template, attributes, template_procs, proc { [attributes, parameters] })
359
+ if the_tag.is_a?(String, Symbol)
360
+ # It's a defined DRYML tag
361
+ send(the_tag, attributes, parameters)
362
+ else
363
+ # It's a proc - restoring a replaced parameter
364
+ the_tag.call(attributes, parameters)
363
365
  end
364
- overriding_proc.call(template_default)
365
- else
366
- if overriding_proc
367
- overriding_attributes, overriding_template_procs = overriding_proc.call
368
-
369
- attributes = merge_attrs(attributes, overriding_attributes)
370
- template_procs = template_procs.merge(overriding_template_procs)
371
- end
372
-
373
- send(the_template, attributes, template_procs)
374
366
  end
375
367
  end
376
-
377
- # Takes two procs that each returh hashes and returns a single
378
- # proc that calls these in turn and merges the results into a
379
- # single hash
380
- def merge_block_tag_parameter(general_proc, overriding_proc)
368
+
369
+
370
+ # This proc is used where 'param' is declared on a tag that is
371
+ # itself a parameter tag. Takes two procs that each return a pair
372
+ # of hashes (attributes and parameters). Returns a single proc
373
+ # that also returns a pair of hashes - the merged atributes and
374
+ # parameters.
375
+ def merge_tag_parameter(general_proc, overriding_proc)
381
376
  if overriding_proc.nil?
382
377
  general_proc
383
378
  else
@@ -386,38 +381,35 @@ module Hobo::Dryml
386
381
  overriding_proc
387
382
  else
388
383
  proc do
389
- overriding_attrs = overriding_proc.call
390
- defined_attrs = general_proc.call
384
+ overriding_attrs, overriding_parameters = overriding_proc.call
385
+ general_attrs, general_parameters = general_proc.call
391
386
 
392
- attrs = merge_attrs(defined_attrs, overriding_attrs)
387
+ attrs = merge_attrs(general_attrs, overriding_attrs)
388
+ overriding_default = overriding_parameters.delete(:default)
389
+ params = general_parameters.merge(overriding_parameters)
393
390
 
394
- # The overrider should provide its tagbody as the new
395
- # <default_tagbody/>
396
- if overriding_attrs[:tagbody] && defined_attrs[:tagbody]
397
- attrs[:tagbody] = proc do |default|
398
- overriding_attrs[:tagbody].call(proc { _output(defined_attrs[:tagbody].call(default)) })
399
- end
391
+ # The overrider should provide its :default as the new
392
+ # 'default_content'
393
+ if overriding_default
394
+ params[:default] =
395
+ if general_parameters[:default]
396
+ proc do |default|
397
+ overriding_default.call(proc { new_context { _output(general_parameters[:default].call(default)) } } )
398
+ end
399
+ else
400
+ proc do |default|
401
+ overriding_default.call(default)
402
+ end
403
+ end
400
404
  end
401
405
 
402
- attrs
406
+ [attrs, params]
403
407
  end
404
408
  end
405
409
  end
406
410
  end
407
411
 
408
- # Same as merge_option_procs, except these procs return a pair of
409
- # hashes rather than a single hash. The first hash is the tag
410
- # attributes, the second is a hash of procs -- the template
411
- # parameters.
412
- def merge_template_parameter(general_proc, overriding_proc)
413
- proc do
414
- general_attributes, general_template_procs = general_proc.call
415
- overriding_attributes, overriding_template_procs = overriding_proc.call
416
- [merge_attrs(general_attributes, overriding_attributes), general_template_procs.merge(overriding_template_procs)]
417
- end
418
- end
419
-
420
-
412
+
421
413
  def part_contexts_storage_tag
422
414
  storage = part_contexts_storage
423
415
  storage.blank? ? "" : "<script>\n#{storage}</script>\n"
@@ -430,25 +422,68 @@ module Hobo::Dryml
430
422
 
431
423
 
432
424
  def render_tag(tag_name, attributes)
433
- if respond_to?(tag_name)
434
- (send(tag_name, attributes) + part_contexts_storage_tag).strip
425
+ method_name = tag_name.gsub('-', '_')
426
+ if respond_to?(method_name)
427
+ (send(method_name, attributes) + part_contexts_storage_tag).strip
435
428
  else
436
429
  false
437
430
  end
438
431
  end
439
432
 
440
433
 
434
+ def element(name, attributes, content=nil, escape = true, &block)
435
+ unless attributes.blank?
436
+ attrs = []
437
+ if escape
438
+ attributes.each do |key, value|
439
+ next unless value
440
+ key = key.to_s.gsub("_", "-")
441
+
442
+ value = if ActionView::Helpers::TagHelper::BOOLEAN_ATTRIBUTES.include?(key)
443
+ key
444
+ else
445
+ # escape once
446
+ value.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
447
+ end
448
+ attrs << %(#{key}="#{value}")
449
+ end
450
+
451
+ else
452
+ attrs = options.map do |key, value|
453
+ key = key.to_s.gsub("_", "-")
454
+ %(#{key}="#{value}")
455
+ end
456
+ end
457
+ attr_string = " #{attrs.sort * ' '}" unless attrs.empty?
458
+ end
459
+
460
+ content = new_context(&block) if block_given?
461
+ res = if content
462
+ "<#{name}#{attr_string}>#{content}</#{name}>"
463
+ else
464
+ "<#{name}#{attr_string} />"
465
+ end
466
+ if block && eval("defined? _erbout", block.binding) # in erb context
467
+ _output(res)
468
+ else
469
+ res
470
+ end
471
+ end
472
+
473
+
441
474
  def session
442
475
  @view ? @view.session : {}
443
476
  end
444
477
 
445
478
 
446
479
  def method_missing(name, *args, &b)
447
- @view.send(name, *args, &b)
480
+ if @view
481
+ @view.send(name, *args, &b)
482
+ else
483
+ raise NoMethodError, name.to_s
484
+ end
448
485
  end
449
486
 
450
-
451
487
  end
452
-
453
488
 
454
489
  end
@@ -45,13 +45,19 @@ module Hobo
45
45
  def object_url(*args)
46
46
  params = args.extract_options!
47
47
  obj, action = args
48
-
49
48
  action &&= action.to_s
50
49
 
51
50
  controller_name = controller_for(obj)
52
51
 
53
52
  subsite = params[:subsite] || self.subsite
54
- base = subsite ? "/#{subsite}#{base_url}" : base_url
53
+
54
+ # TODO - what if you want if_available as a query param?
55
+ if_available = params.delete(:if_available)
56
+ return nil if if_available &&
57
+ ((action.nil? && obj.respond_to?(:typed_id) && !linkable?(obj.class, :show, subsite)) ||
58
+ (action.nil? && obj.is_a?(Class) && !linkable?(obj, :index, subsite)))
59
+
60
+ base = subsite.blank? ? base_url : "/#{subsite}#{base_url}"
55
61
 
56
62
  parts = if obj.is_a? Class
57
63
  [base, controller_name]
@@ -238,7 +244,7 @@ module Hobo
238
244
  if s.is_a? Hobo::RawJs
239
245
  s.to_s
240
246
  else
241
- "'" + s.gsub("'"){"\\'"} + "'"
247
+ "'" + s.to_s.gsub("'"){"\\'"} + "'"
242
248
  end
243
249
  end
244
250
 
@@ -349,7 +355,12 @@ module Hobo
349
355
  HashWithIndifferentAccess.new
350
356
  end
351
357
  end
352
-
358
+
359
+ def linkable?(obj, action, subsite=self.subsite)
360
+ Hobo::ModelRouter.linkable?(subsite, obj, action)
361
+ end
362
+
363
+
353
364
  # debugging support
354
365
 
355
366
  def abort_with(*args)
@@ -17,13 +17,18 @@ module Hobo
17
17
  Hobo.register_model(base)
18
18
  base.extend(ClassMethods)
19
19
  base.class_eval do
20
- @field_specs = HashWithIndifferentAccess.new
21
- set_field_type({})
22
20
  alias_method_chain :attributes=, :hobo_type_conversion
23
21
  end
24
22
  class << base
25
23
  alias_method_chain :has_many, :defined_scopes
26
24
  alias_method_chain :belongs_to, :foreign_key_declaration
25
+ alias_method_chain :acts_as_list, :fields if defined?(ActiveRecord::Acts::List)
26
+ def inherited(klass)
27
+ fields do
28
+ Hobo.register_model(klass)
29
+ field(klass.inheritance_column, :string)
30
+ end
31
+ end
27
32
  end
28
33
  end
29
34
 
@@ -70,9 +75,17 @@ module Hobo
70
75
  end
71
76
  res
72
77
  end
73
-
74
-
75
- attr_reader :field_specs
78
+
79
+
80
+ def acts_as_list_with_fields(options = {})
81
+ fields { |f| f.send(options._?[:column] || "position", :integer) }
82
+ acts_as_list_without_fields(options)
83
+ end
84
+
85
+
86
+ def field_specs
87
+ @field_specs ||= HashWithIndifferentAccess.new
88
+ end
76
89
  public :field_specs
77
90
 
78
91
  def set_field_type(types)
@@ -108,7 +121,7 @@ module Hobo
108
121
  end
109
122
 
110
123
  def never_show?(field)
111
- @hobo_never_show && field.to_sym.in?(@hobo_never_show)
124
+ (@hobo_never_show && field.to_sym.in?(@hobo_never_show)) || (superclass < Hobo::Model && superclass.never_show?(field))
112
125
  end
113
126
  public :never_show?
114
127
 
@@ -157,7 +170,7 @@ module Hobo
157
170
  end
158
171
 
159
172
  class_eval %{
160
- def self.find_by_id_name(id_name, options)
173
+ def self.find_by_id_name(id_name, options={})
161
174
  #{finder}
162
175
  end
163
176
  }
@@ -381,9 +394,11 @@ module Hobo
381
394
  end
382
395
 
383
396
  if find_scope
397
+ scope_name = "@#{name.to_s.gsub('?','')}_scope"
398
+
384
399
  # Calling instance_variable_get directly causes self to
385
400
  # get loaded, hence this trick
386
- assoc = Kernel.instance_method(:instance_variable_get).bind(self).call("@#{name}_scope")
401
+ assoc = Kernel.instance_method(:instance_variable_get).bind(self).call(scope_name)
387
402
 
388
403
  unless assoc
389
404
  options = proxy_reflection.options
@@ -418,7 +433,7 @@ module Hobo
418
433
  end.new(self.proxy_owner, r)
419
434
 
420
435
  # Calling directly causes self to get loaded
421
- Kernel.instance_method(:instance_variable_set).bind(self).call("@#{name}_scope", assoc)
436
+ Kernel.instance_method(:instance_variable_set).bind(self).call(scope_name, assoc)
422
437
  end
423
438
  assoc
424
439
  else
@@ -442,9 +457,9 @@ module Hobo
442
457
  end
443
458
 
444
459
 
445
- def attributes_with_hobo_type_conversion=(attributes)
460
+ def attributes_with_hobo_type_conversion=(attributes, guard_protected_attributes=true)
446
461
  converted = attributes.map_hash { |k, v| convert_type_for_mass_assignment(self.class.field_type(k), v) }
447
- self.attributes_without_hobo_type_conversion = converted
462
+ send(:attributes_without_hobo_type_conversion=, converted, guard_protected_attributes)
448
463
  end
449
464
 
450
465
 
@@ -529,12 +544,16 @@ module Hobo
529
544
  elsif value.is_a? String
530
545
  dt = parse_datetime(value)
531
546
  dt && dt.to_date
547
+ else
548
+ value
532
549
  end
533
550
  elsif field_type <= Time
534
551
  if value.is_a? Hash
535
552
  Time.local(*(%w{year month day hour minute}.map{|s| value[s].to_i}))
536
553
  elsif value.is_a? String
537
554
  parse_datetime(value)
555
+ else
556
+ value
538
557
  end
539
558
  elsif field_type <= TrueClass
540
559
  (value.is_a?(String) && value.strip.downcase.in?(['0', 'false']) || value.blank?) ? false : true