hobo 0.5.3 → 0.6

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 (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
@@ -6,7 +6,7 @@ module Hobo
6
6
 
7
7
  class PermissionDeniedError < RuntimeError; end
8
8
 
9
- VIEWLIB_DIR = "hobolib"
9
+ VIEWLIB_DIR = "taglibs"
10
10
 
11
11
  GENERIC_PAGE_TAGS = [:index, :show, :new, :edit, :show_collection, :new_in_collection]
12
12
 
@@ -16,17 +16,13 @@ module Hobo
16
16
  base.extend(ClassMethods)
17
17
  base.helper_method(:find_partial, :model, :current_user)
18
18
 
19
- Hobo::ControllerHelpers.public_instance_methods.each {|m| base.hide_action(m)}
20
-
21
19
  for collection in base.collections
22
20
  add_collection_actions(base, collection.to_sym)
23
21
  end
24
22
 
25
23
  base.before_filter :set_no_cache_headers
26
-
27
- base.class_eval do
28
- alias_method_chain :redirect_to, :object_url
29
- end
24
+
25
+ Hobo::Controller.included_in_class(base)
30
26
  end
31
27
 
32
28
  def find_partial(klass, as)
@@ -36,7 +32,8 @@ module Hobo
36
32
 
37
33
  def template_path(dir, name, is_partial)
38
34
  fileRx = is_partial ? /^_#{name}\.[^.]+/ : /^#{name}\.[^.]+/
39
- unless Dir.entries("#{RAILS_ROOT}/app/views/#{dir}").grep(fileRx).empty?
35
+ full_dir = "#{RAILS_ROOT}/app/views/#{dir}"
36
+ unless !File.exists?(full_dir) || Dir.entries(full_dir).grep(fileRx).empty?
40
37
  return "#{dir}/#{name}"
41
38
  end
42
39
  end
@@ -131,7 +128,7 @@ module Hobo
131
128
  def show_action(*names)
132
129
  show_actions.concat(names)
133
130
  for name in names
134
- class_eval "def #{name}; show; end"
131
+ class_eval "def #{name}; hobo_show; end"
135
132
  end
136
133
  end
137
134
 
@@ -201,7 +198,7 @@ module Hobo
201
198
  def hobo_index(options = {})
202
199
  options = LazyHash.new(options)
203
200
  @model = model
204
- @this = options[:collection] || paginated_find
201
+ @this = options[:collection] || paginated_find(options)
205
202
 
206
203
  instance_variable_set("@#{@model.name.pluralize.underscore}", @this)
207
204
  if block_given?
@@ -216,15 +213,18 @@ module Hobo
216
213
  options = extract_options_from_args!(args)
217
214
 
218
215
  total_number = options.delete(:total_number)
219
- if args.empty?
220
- total_number ||= count_with_data_filter
221
- else
222
- owner, collection_name = args
223
- @association = collection_name.to_s.split(".").inject(owner) { |m, name| m.send(name) }
224
- total_number ||= @association.size
225
- @reflection = @association.proxy_reflection
216
+ @association = options.delete(:association) or
217
+ if args.any?
218
+ owner, collection_name = args
219
+ @association = collection_name.to_s.split(".").inject(owner) { |m, name| m.send(name) }
220
+ end
221
+
222
+ if @association
223
+ total_number ||= @association.count
224
+ @reflection = @association.proxy_reflection if @association.respond_to?(:proxy_reflection)
226
225
  end
227
226
 
227
+ total_number ||= count_with_data_filter
228
228
  page_size = options.delete(:page_size) || 20
229
229
  page = options.delete(:page) || params[:page]
230
230
  @pages = ::ActionController::Pagination::Paginator.new(self, total_number, page_size, page)
@@ -237,7 +237,7 @@ module Hobo
237
237
  if @association
238
238
  @association.find(:all, options, &b)
239
239
  else
240
- options[:order] = :default
240
+ options[:order] ||= :default
241
241
  find_with_data_filter(options, &b)
242
242
  end
243
243
  end
@@ -262,7 +262,8 @@ module Hobo
262
262
  if @this
263
263
  if Hobo.can_view?(current_user, @this)
264
264
  set_named_this!
265
- block_given? ? yield : hobo_render
265
+ yield if block_given?
266
+ hobo_render unless performed?
266
267
  else
267
268
  permission_denied(options)
268
269
  end
@@ -273,40 +274,41 @@ module Hobo
273
274
  def hobo_new(options={})
274
275
  options = LazyHash.new(options)
275
276
  @this = options[:this] || model.new
276
- @this.created_by(current_user) unless options.has_key?(:set_creator) && !options[:set_creator]
277
+ @this.set_creator(current_user) unless options.has_key?(:set_creator) && !options[:set_creator]
277
278
 
278
279
  if Hobo.can_create?(current_user, @this)
279
280
  set_named_this!
280
- block_given? ? yield : hobo_render
281
+ yield if block_given?
282
+ hobo_render unless performed?
281
283
  else
282
284
  permission_denied(options)
283
285
  end
284
286
  end
285
287
 
286
-
288
+
287
289
  def hobo_create(options={})
288
290
  options = LazyHash.new(options)
289
291
 
290
- @this = (options[:this] ||
291
- begin
292
- attributes = params[model.name.underscore]
293
- type_attr = params['type']
294
- create_model = if 'type'.in?(model.column_names) and
295
- type_attr and type_attr.in?(model.send(:subclasses).omap{name})
296
- type_attr.constantize
297
- else
298
- model
299
- end
300
- this = create_model.new
301
- @check_create_permission = [this]
302
- initialize_from_params(this, attributes)
303
- for obj in @check_create_permission
304
- permission_denied(options) and return unless Hobo.can_create?(current_user, obj)
305
- end
306
- @check_create_permission = nil
307
- this
308
- end)
309
-
292
+ if (@this = options[:this])
293
+ permission_denied(options) and return unless Hobo.can_create?(current_user, @this)
294
+ else
295
+ attributes = params[model.name.underscore]
296
+ type_attr = params['type']
297
+ create_model = if 'type'.in?(model.column_names) and
298
+ type_attr and type_attr.in?(model.send(:subclasses).omap{name})
299
+ type_attr.constantize
300
+ else
301
+ model
302
+ end
303
+ @this = create_model.new
304
+ @check_create_permission = [@this]
305
+ initialize_from_params(@this, attributes)
306
+ for obj in @check_create_permission
307
+ permission_denied(options) and return unless Hobo.can_create?(current_user, obj)
308
+ end
309
+ @check_create_permission = nil
310
+ end
311
+
310
312
  set_named_this!
311
313
  if @this.save
312
314
  if block_given?
@@ -375,8 +377,9 @@ module Hobo
375
377
  overridable_response(options, :js_response) do
376
378
  if changes.size == 1
377
379
  # Decreasingly hacky support for the scriptaculous in-place-editor
378
- new_val = Hobo::Dryml.render_tag(@template, "show",
379
- :obj => @this, :attr => changes.keys.first, :no_span => true)
380
+ new_val = Hobo::Dryml.render_tag(@template, "view",
381
+ :with => @this, :field => changes.keys.first,
382
+ :no_wrapper => true)
380
383
  hobo_ajax_response(@this, :new_field_value => new_val)
381
384
  else
382
385
  hobo_ajax_response(@this)
@@ -457,8 +460,8 @@ module Hobo
457
460
  permission_denied(options) and return unless Hobo.can_view?(current_user, @owner, collection)
458
461
 
459
462
  @association = options[:collection] || @owner.send(collection)
460
- @this = options[:this] || @association.new_without_appending
461
- @this.created_by(current_user) unless options.has_key?(:set_creator) && !options[:set_creator]
463
+ @this = options[:this] || @association.new
464
+ @this.set_creator(current_user) unless options.has_key?(:set_creator) && !options[:set_creator]
462
465
 
463
466
  permission_denied(options) and return unless Hobo.can_create?(current_user, @this)
464
467
 
@@ -533,7 +536,7 @@ module Hobo
533
536
  true
534
537
  else
535
538
  if page_kind.in? GENERIC_PAGE_TAGS
536
- render_tag("#{page_kind}_page", :obj => @this)
539
+ render_tag("#{page_kind.to_s.camelize}Page", :with => @this)
537
540
  true
538
541
  else
539
542
  false
@@ -586,7 +589,7 @@ module Hobo
586
589
 
587
590
  def initialize_from_params(obj, params)
588
591
  update_with_params(obj, params)
589
- obj.created_by(current_user)
592
+ obj.set_creator(current_user)
590
593
  (@check_create_permission ||= []) << obj
591
594
  obj
592
595
  end
@@ -627,7 +630,9 @@ module Hobo
627
630
 
628
631
 
629
632
  def param_to_value(field_type, value)
630
- if field_type <= Date
633
+ if field_type.nil?
634
+ value
635
+ elsif field_type <= Date
631
636
  if value.is_a? Hash
632
637
  Date.new(*(%w{year month day}.map{|s| value[s].to_i}))
633
638
  elsif value.is_a? String
@@ -640,6 +645,8 @@ module Hobo
640
645
  elsif value.is_a? String
641
646
  parse_datetime(value)
642
647
  end
648
+ elsif field_type <= TrueClass
649
+ (value.is_a?(String) && value.strip.downcase.in?(['0', 'false']) || value.blank?) ? false : true
643
650
  else
644
651
  # primitive field
645
652
  value
@@ -1,3 +1,5 @@
1
1
  class Hobo::PasswordString < String
2
+
3
+ COLUMN_TYPE = :string
2
4
 
3
5
  end
@@ -0,0 +1,75 @@
1
+ module ::Hobo::Plugins
2
+ class HoboPlugin
3
+
4
+ def initialize(opt=nil)
5
+ @opt = opt || Hash.new
6
+ set_up_options(self.class::PLUGIN_DEFAULTS)
7
+
8
+ send @opt[:setup_using] || :default
9
+ end
10
+
11
+ def set_up_options(*defaults)
12
+ @opt = @opt.reverse_merge(*defaults)
13
+ make_variations(self.class::PLUGIN_SYMBOLS)
14
+ end
15
+
16
+ def make_variations(h)
17
+ h.each do |name|
18
+ if @opt[name] && @opt[name] != false
19
+ # start with :product_category
20
+
21
+ # add :product_categories
22
+ @opt[name.to_s.pluralize.to_sym] = @opt[name].to_s.pluralize.to_sym
23
+
24
+ # :ProductCategory
25
+ @opt[name.to_s.camelize.to_sym] = @opt[name].to_s.camelize.to_sym
26
+
27
+ # :ProductCategories
28
+ @opt[name.to_s.camelize.pluralize.to_sym] = @opt[name].to_s.camelize.pluralize.to_sym
29
+
30
+ # :ProductCategoriesController
31
+ @opt[(name.to_s.camelize.pluralize+'Controller').to_sym] =
32
+ (@opt[name].to_s.camelize.pluralize+'Controller').to_sym
33
+ else
34
+ @opt[name.to_s.pluralize.to_sym] = false
35
+ end
36
+ end
37
+ end
38
+
39
+ def hobo_model(name, &b)
40
+ make_class @opt[name], ActiveRecord::Base do
41
+ hobo_model
42
+ class_eval &b if b
43
+ end
44
+ end
45
+
46
+ def resource_controller(name, &b)
47
+ make_class @opt[name], ApplicationController do
48
+ hobo_model_controller
49
+
50
+ class_eval &b if b
51
+ end
52
+ end
53
+
54
+ def make_class(class_name, base_class, &b)
55
+ opt = @opt
56
+ c = Class.new(base_class)
57
+ silence_warnings { Object.const_set(class_name, c) }
58
+ c.class_eval do
59
+ @plugin_opt = opt
60
+ def self.sym
61
+ @plugin_opt
62
+ end
63
+ def self.has_feature(name)
64
+ !@plugin_opt[name].nil? && @plugin_opt[name] != false
65
+ end
66
+ def sym
67
+ self.class.sym
68
+ end
69
+ end
70
+ c.class_eval &b if b
71
+ c
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,98 @@
1
+ module Hobo::RapidHelper
2
+
3
+ def options_for_hobo_ajax(options)
4
+ js_options = build_callbacks(options)
5
+
6
+ js_options['asynchronous'] = false if options[:type] == :synchronous
7
+ js_options['method'] = method_option_to_s(options[:method]) if options[:method]
8
+ js_options['evalScripts'] = false if options[:script] == false
9
+ js_options['form'] = options[:form] if options[:form]
10
+ js_options['params'] = make_params_js(options[:params]) if options[:params]
11
+ js_options['resultUpdate'] = js_result_updates(options[:result_update]) if options[:result_update]
12
+ js_options['resetForm'] = false if options[:reset_form] == false
13
+ js_options['refocusForm'] = false if options[:refocus_form] == false
14
+
15
+ js_options.empty? ? nil : options_for_javascript(js_options)
16
+ end
17
+
18
+
19
+ def js_updates(updates)
20
+ return '[]' unless updates
21
+ updates = [updates] unless updates.is_a? Array
22
+ '[' + comma_split(updates).map{|u| js_str(u)}.join(', ') + ']'
23
+ end
24
+
25
+
26
+ def js_result_updates(updates)
27
+ return '[]' unless updates
28
+ updates = [updates] unless updates.is_a? Array
29
+ pairs = comma_split(updates).omap{split(/\s*=\s*/)}
30
+ '[' + pairs.map{|p| "{id: #{js_str(p[0])}, result: #{js_str(p[1])}}"}.join(", ") + ']'
31
+ end
32
+
33
+
34
+ def ajax_updater(url_or_form, message, update, options={})
35
+ options ||= {}
36
+ options.symbolize_keys!
37
+
38
+ target = if url_or_form == :post_form
39
+ target = "this"
40
+ else
41
+ js_str(url_or_form)
42
+ end
43
+ js_options = options_for_hobo_ajax(options)
44
+ args = [target, js_str(message || "..."), js_updates(update), js_options].compact
45
+
46
+ confirm = options.delete(:confirm)
47
+
48
+ func = "Hobo.ajaxRequest(#{args * ', '})"
49
+ if confirm
50
+ "if (confirm(#{js_str(confirm)})) { #{func} }"
51
+ else
52
+ func
53
+ end
54
+ end
55
+
56
+
57
+ def a_or_an(word)
58
+ if word =~ /^[aeiouh]/
59
+ "an #{word}"
60
+ else
61
+ "a #{word}"
62
+ end
63
+ end
64
+
65
+
66
+ def no_break(s)
67
+ s = new_context { yield } if block_given?
68
+ s.gsub(' ', '&nbsp;')
69
+ end
70
+
71
+
72
+
73
+
74
+ def in_place_editor(behaviour_class, attributes)
75
+ blank_message = attributes.delete(:blank_message) || "(click to edit)"
76
+
77
+ attributes = add_classes(attributes, behaviour_class)
78
+ attributes.update(:hobo_model_id => this_field_dom_id,
79
+ :hobo_blank_message => blank_message,
80
+ :if_blank => blank_message)
81
+
82
+ update = attributes.delete(:update)
83
+ attributes[:hobo_update] = update if update
84
+
85
+ view(attributes)
86
+ end
87
+
88
+
89
+
90
+ AJAX_ATTRS = [:before, :success, :failure, :complete, :type, :method,
91
+ :script, :form, :params, :confirm,
92
+ :reset_form, :refocus_form, :result_update]
93
+
94
+
95
+ def editor_class
96
+ end
97
+
98
+ end
@@ -1,4 +1,3 @@
1
- a
2
1
  abbr
3
2
  acronym
4
3
  address
@@ -30,7 +29,6 @@ em
30
29
  embed
31
30
  fieldset
32
31
  font
33
- form
34
32
  frame
35
33
  frameset
36
34
  h1
@@ -45,7 +43,6 @@ html
45
43
  i
46
44
  iframe
47
45
  img
48
- input
49
46
  ins
50
47
  isindex
51
48
  kbd
@@ -1,7 +1,9 @@
1
1
  class Hobo::TextileString < String
2
2
 
3
+ COLUMN_TYPE = :text
4
+
3
5
  def to_html
4
- if text.blank?
6
+ if blank?
5
7
  ""
6
8
  else
7
9
  textilized = RedCloth.new(self, [ :hard_breaks ])
@@ -11,3 +13,11 @@ class Hobo::TextileString < String
11
13
  end
12
14
 
13
15
  end
16
+
17
+ class RedCloth
18
+ # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet.
19
+ # http://code.whytheluckystiff.net/redcloth/changeset/128
20
+ def hard_break( text )
21
+ text.gsub!( /(.)\n(?!\n|\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks && RedCloth::VERSION == "3.0.4"
22
+ end
23
+ end
@@ -31,7 +31,7 @@ module Hobo
31
31
  end
32
32
 
33
33
  def method_missing(name, *args)
34
- raise UndefinedAccessError.new("call to: #{name}")
34
+ raise UndefinedAccessError.new("call to: Hobo::Undefined##{name}")
35
35
  end
36
36
 
37
37
  undef_method :==