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
@@ -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 :==