hobo 0.6.4 → 0.7.0

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