hobo 0.7.0 → 0.7.1

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 (48) hide show
  1. data/hobo_files/plugin/CHANGES.txt +220 -23
  2. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +18 -25
  3. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +20 -15
  4. data/hobo_files/plugin/generators/hobo_model/templates/model.rb +3 -3
  5. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +3 -3
  6. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.css +1 -2
  7. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.js +21 -4
  8. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/fieldbg.gif +0 -0
  9. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/spinner.gif +0 -0
  10. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +154 -26
  11. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +144 -0
  12. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +1 -1
  13. data/hobo_files/plugin/generators/hobo_user_controller/templates/controller.rb +1 -1
  14. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +8 -11
  15. data/hobo_files/plugin/init.rb +0 -2
  16. data/hobo_files/plugin/lib/active_record/has_many_association.rb +0 -9
  17. data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +0 -10
  18. data/hobo_files/plugin/lib/hobo.rb +57 -44
  19. data/hobo_files/plugin/lib/hobo/bundle.rb +222 -0
  20. data/hobo_files/plugin/lib/hobo/controller.rb +2 -5
  21. data/hobo_files/plugin/lib/hobo/dryml.rb +8 -7
  22. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +10 -21
  23. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +107 -80
  24. data/hobo_files/plugin/lib/hobo/dryml/template.rb +27 -20
  25. data/hobo_files/plugin/lib/hobo/enum_string.rb +1 -1
  26. data/hobo_files/plugin/lib/hobo/field_declaration_dsl.rb +7 -0
  27. data/hobo_files/plugin/lib/hobo/guest.rb +4 -0
  28. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +37 -9
  29. data/hobo_files/plugin/lib/hobo/model.rb +79 -17
  30. data/hobo_files/plugin/lib/hobo/model_controller.rb +59 -60
  31. data/hobo_files/plugin/lib/hobo/model_router.rb +16 -4
  32. data/hobo_files/plugin/lib/hobo/rapid_helper.rb +2 -1
  33. data/hobo_files/plugin/lib/hobo/user.rb +10 -7
  34. data/hobo_files/plugin/lib/hobo/user_controller.rb +6 -6
  35. data/hobo_files/plugin/{tags → taglibs}/core.dryml +5 -4
  36. data/hobo_files/plugin/{tags → taglibs}/rapid.dryml +54 -7
  37. data/hobo_files/plugin/{tags → taglibs}/rapid_document_tags.dryml +0 -0
  38. data/hobo_files/plugin/{tags → taglibs}/rapid_editing.dryml +4 -2
  39. data/hobo_files/plugin/{tags → taglibs}/rapid_forms.dryml +1 -4
  40. data/hobo_files/plugin/{tags → taglibs}/rapid_navigation.dryml +1 -2
  41. data/hobo_files/plugin/taglibs/rapid_pages.dryml +411 -0
  42. data/hobo_files/plugin/{tags → taglibs}/rapid_plus.dryml +0 -0
  43. data/hobo_files/plugin/{tags → taglibs}/rapid_support.dryml +9 -6
  44. data/hobo_files/plugin/tasks/fix_dryml.rake +0 -1
  45. metadata +16 -14
  46. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid_ui.css +0 -167
  47. data/hobo_files/plugin/lib/hobo/plugins.rb +0 -75
  48. data/hobo_files/plugin/tags/rapid_pages.dryml +0 -341
@@ -64,7 +64,7 @@ module Hobo::Dryml
64
64
 
65
65
  def build(local_names, auto_taglibs)
66
66
 
67
- auto_taglibs.each{|t| import_taglib(t)}
67
+ auto_taglibs.each { |t| import_taglib(t) }
68
68
 
69
69
  @build_instructions.each do |instruction|
70
70
  name = instruction[:name]
@@ -82,7 +82,7 @@ module Hobo::Dryml
82
82
  @environment.class_eval(method_src, template_path, instruction[:line_num])
83
83
 
84
84
  when :include
85
- import_taglib(name, instruction[:as])
85
+ import_taglib(instruction)
86
86
 
87
87
  when :module
88
88
  import_module(name.constantize, instruction[:as])
@@ -102,24 +102,13 @@ module Hobo::Dryml
102
102
  end
103
103
 
104
104
 
105
- def expand_template_path(path)
106
- base = if path.starts_with? "plugins"
107
- "vendor/" + path
108
- elsif path.include?("/")
109
- "app/views/#{path}"
110
- else
111
- template_dir = File.dirname(template_path)
112
- "#{template_dir}/#{path}"
113
- end
114
- base + ".dryml"
115
- end
116
-
117
-
118
- def import_taglib(src_path, as=nil)
119
- path = expand_template_path(src_path)
120
- unless template_path == path
121
- taglib = Taglib.get(RAILS_ROOT + (path.starts_with?("/") ? path : "/" + path))
122
- taglib.import_into(@environment, as)
105
+ def import_taglib(options)
106
+ if options[:module]
107
+ import_module(options[:module].constantize, options[:as])
108
+ else
109
+ template_dir = File.dirname(template_path)
110
+ taglib = Taglib.get(options.merge(:template_dir => template_dir))
111
+ taglib.import_into(@environment, options[:as])
123
112
  end
124
113
  end
125
114
 
@@ -133,7 +122,7 @@ module Hobo::Dryml
133
122
  def set_theme(name)
134
123
  if Hobo.current_theme.nil? or Hobo.current_theme == name
135
124
  Hobo.current_theme = name
136
- import_taglib("taglibs/themes/#{name}/application")
125
+ import_taglib(:src => "taglibs/themes/#{name}/application")
137
126
  end
138
127
  end
139
128
  end
@@ -1,95 +1,122 @@
1
- module Hobo::Dryml
1
+ module Hobo
2
+
3
+ module Dryml
2
4
 
3
- class Taglib
4
-
5
- @cache = {}
6
-
7
- class << self
8
-
9
- def get(path)
10
- raise DrymlException, "No such taglib: #{path}" unless File.exists?(path)
11
- file = File.new(path)
12
-
13
- taglib = @cache[file.path]
14
- if taglib
15
- taglib.reload
16
- else
17
- taglib = Taglib.new(file)
18
- @cache[file.path] = taglib
5
+ class Taglib
6
+
7
+ @cache = {}
8
+
9
+ class << self
10
+
11
+ def get(options)
12
+ file = taglib_file(options)
13
+
14
+ taglib = @cache[options]
15
+ if taglib
16
+ taglib.reload
17
+ else
18
+ renames = (bundle = options[:bundle] and
19
+ Bundle.bundles[bundle]._?.renames)
20
+
21
+ taglib = Taglib.new(file, renames)
22
+ @cache[options] = taglib
23
+ end
24
+ taglib
19
25
  end
20
- taglib
21
- end
22
-
23
- def clear_cache
24
- @cache = {}
25
- end
26
-
27
- end
28
-
29
- def initialize(file)
30
- @file = file
31
- load
32
- end
33
-
34
- def reload
35
- load if @file.mtime > @last_load_time
36
- end
37
-
38
- def load
39
- @module = Module.new do
40
26
 
41
- @tag_attrs = {}
42
- @tag_aliases = {}
27
+ def clear_cache
28
+ @cache = {}
29
+ end
30
+
31
+ private
43
32
 
44
- class << self
33
+ def taglib_file(options)
34
+ base = if (plugin = options[:plugin])
35
+ "vendor/plugins/#{plugin}/taglibs"
36
+ elsif (bundle_name = options[:bundle])
37
+ bundle = Bundle.bundles[bundle_name]
38
+ "vendor/plugins/#{bundle.plugin}/taglibs"
39
+ elsif options[:src] =~ /\//
40
+ "app/views"
41
+ else
42
+ options[:template_dir]
43
+ end
45
44
 
46
- def included(base)
47
- @tag_aliases.each do |tag, feature|
48
- base.send(:alias_method_chain, tag, feature)
49
- end
50
- end
51
-
52
- def _register_tag_attrs(tag, attrs)
53
- @tag_attrs[tag] = attrs
54
- end
55
- attr_reader :tag_attrs
45
+ filename = "#{RAILS_ROOT}/#{base}/#{options[:src]}.dryml"
46
+ raise DrymlException, "No such taglib: #{options.inspect} #{filename}" unless File.exists?(filename)
47
+ File.new(filename)
48
+ end
49
+
50
+ end
51
+
52
+ def initialize(file, renames)
53
+ @file = file
54
+ @renames = renames
55
+ load
56
+ end
57
+
58
+ def reload
59
+ load if @file.mtime > @last_load_time
60
+ end
61
+
62
+ def load
63
+ @module = Module.new do
64
+
65
+ @tag_attrs = {}
66
+ @tag_aliases = {}
56
67
 
57
- def delayed_alias_method_chain(tag, feature)
58
- @tag_aliases[tag] = feature
68
+ class << self
69
+
70
+ def included(base)
71
+ @tag_aliases.each do |tag, feature|
72
+ base.send(:alias_method_chain, tag, feature)
73
+ end
74
+ end
75
+
76
+ def _register_tag_attrs(tag, attrs)
77
+ @tag_attrs[tag] = attrs
78
+ end
79
+ attr_reader :tag_attrs
80
+
81
+ def delayed_alias_method_chain(tag, feature)
82
+ @tag_aliases[tag] = feature
83
+ end
84
+
59
85
  end
60
86
 
61
87
  end
62
-
88
+ @file.rewind
89
+ template = Template.new(@file.read, @module, @file.path, @renames)
90
+ template.compile([], [])
91
+ @last_load_time = @file.mtime
63
92
  end
64
- @file.rewind
65
- template = Template.new(@file.read, @module, @file.path)
66
- template.compile([], [])
67
- @last_load_time = @file.mtime
68
- end
69
-
70
- def import_into(class_or_module, as)
71
- if as
72
- # Define a method on class_or_module named whatever 'as'
73
- # is. The first time the method is called it creates and
74
- # returns an object that provides the taglib's tags as
75
- # methods. On subsequent calls the object is cached in an
76
- # instance variable "@_#{as}_taglib"
77
-
78
- taglib_module = @module
79
- ivar = "@_#{as}_taglib"
80
- class_or_module.send(:define_method, as) do
81
- instance_variable_get(ivar) or begin
82
- as_class = Class.new(TemplateEnvironment) { include taglib_module }
83
- as_object = as_class.new
84
- as_object.copy_instance_variables_from(self)
85
- instance_variable_set(ivar, as_object)
86
- end
93
+
94
+ def import_into(class_or_module, as)
95
+ if as
96
+ # Define a method on class_or_module named whatever 'as'
97
+ # is. The first time the method is called it creates and
98
+ # returns an object that provides the taglib's tags as
99
+ # methods. On subsequent calls the object is cached in an
100
+ # instance variable "@_#{as}_taglib"
101
+
102
+ taglib_module = @module
103
+ ivar = "@_#{as}_taglib"
104
+ class_or_module.send(:define_method, as) do
105
+ instance_variable_get(ivar) or begin
106
+ as_class = Class.new(TemplateEnvironment) { include taglib_module }
107
+ as_object = as_class.new
108
+ as_object.copy_instance_variables_from(self)
109
+ instance_variable_set(ivar, as_object)
110
+ end
111
+ end
112
+ else
113
+ class_or_module.send(:include, @module)
114
+ class_or_module.tag_attrs.update(@module.tag_attrs) if @module.respond_to?(:tag_attrs)
87
115
  end
88
- else
89
- class_or_module.send(:include, @module)
90
- class_or_module.tag_attrs.update(@module.tag_attrs) if @module.respond_to?(:tag_attrs)
91
116
  end
117
+
92
118
  end
93
-
119
+
94
120
  end
121
+
95
122
  end
@@ -28,12 +28,11 @@ module Hobo::Dryml
28
28
  end
29
29
  end
30
30
 
31
- def initialize(src, environment, template_path)
31
+ def initialize(src, environment, template_path, renames={})
32
32
  @src = src
33
-
34
33
  @environment = environment # a class or a module
35
-
36
34
  @template_path = template_path.sub(/^#{Regexp.escape(RAILS_ROOT)}/, "")
35
+ @class_renames = renames
37
36
 
38
37
  @builder = Template.build_cache[@template_path] || DRYMLBuilder.new(@template_path)
39
38
  @builder.set_environment(environment)
@@ -41,7 +40,7 @@ module Hobo::Dryml
41
40
  @last_element = nil
42
41
  end
43
42
 
44
- attr_reader :tags, :template_path
43
+ attr_reader :tags, :template_path, :class_renames
45
44
 
46
45
  def compile(local_names=[], auto_taglibs=[])
47
46
  now = Time.now
@@ -144,7 +143,8 @@ module Hobo::Dryml
144
143
 
145
144
  when "include"
146
145
  include_element(el)
147
- # return nothing - the include has no presence in the erb source
146
+ # return just the newlines to keep line-number matching - the
147
+ # include has no presence in the erb source
148
148
  tag_newlines(el)
149
149
 
150
150
  when "set-theme"
@@ -179,15 +179,11 @@ module Hobo::Dryml
179
179
  def include_element(el)
180
180
  require_toplevel(el)
181
181
  require_attribute(el, "as", /^#{DRYML_NAME}$/, true)
182
- if el.attributes["src"]
183
- @builder.add_build_instruction(:include,
184
- :name => el.attributes["src"],
185
- :as => el.attributes["as"])
186
- elsif el.attributes["module"]
187
- @builder.add_build_instruction(:module,
188
- :name => el.attributes["module"],
189
- :as => el.attributes["as"])
182
+ options = {}
183
+ %w(src module plugin bundle as).each do |attr|
184
+ options[attr.to_sym] = el.attributes[attr] if el.attributes[attr]
190
185
  end
186
+ @builder.add_build_instruction(:include, options)
191
187
  end
192
188
 
193
189
 
@@ -247,9 +243,12 @@ module Hobo::Dryml
247
243
  unsafe_name = el.attributes["tag"]
248
244
  name = Hobo::Dryml.unreserve(unsafe_name)
249
245
  if (for_type = el.attributes['for'])
250
- type_name = if for_type =~ /^[a-z]/
246
+ type_name = case for_type
247
+ when /^[a-z]/
251
248
  # It's a symbolic type name - look up the Ruby type name
252
249
  Hobo.field_types[for_type].name
250
+ when /^_.*_$/
251
+ rename_class(for_type)
253
252
  else
254
253
  for_type
255
254
  end.underscore.gsub('/', '__')
@@ -420,9 +419,9 @@ module Hobo::Dryml
420
419
  # holding a proc
421
420
  param_restore_local_name(name)
422
421
  elsif (call_type = polymorphic_call_type(el))
423
- "find_polymorphic_tag(:#{name.underscore}, #{call_type})"
422
+ "find_polymorphic_tag(:#{ruby_name name}, #{call_type})"
424
423
  else
425
- ":#{name.underscore}"
424
+ ":#{ruby_name name}"
426
425
  end
427
426
  "call_tag_parameter(#{to_call}, #{args})"
428
427
  else
@@ -430,9 +429,11 @@ module Hobo::Dryml
430
429
  # The tag is a proc available in a local variable
431
430
  "#{param_restore_local_name(name)}.call(#{attributes}, #{parameters})"
432
431
  elsif (call_type = polymorphic_call_type(el))
433
- "send(find_polymorphic_tag(:#{name.underscore}, #{call_type}), #{attributes}, #{parameters})"
432
+ "send(find_polymorphic_tag(:#{ruby_name name}, #{call_type}), #{attributes}, #{parameters})"
433
+ elsif attributes == "{}" && parameters == "{}"
434
+ "#{ruby_name name}.to_s"
434
435
  else
435
- "#{name.underscore}(#{attributes}, #{parameters})"
436
+ "#{ruby_name name}(#{attributes}, #{parameters})"
436
437
  end
437
438
  end
438
439
 
@@ -524,7 +525,7 @@ module Hobo::Dryml
524
525
 
525
526
 
526
527
  def param_restore_local_name(name)
527
- "_#{name.underscore}_restore"
528
+ "_#{ruby_name name}_restore"
528
529
  end
529
530
 
530
531
 
@@ -549,7 +550,7 @@ module Hobo::Dryml
549
550
 
550
551
 
551
552
  def param_content_local_name(name)
552
- "_#{name.underscore}__default_content"
553
+ "_#{ruby_name name}__default_content"
553
554
  end
554
555
 
555
556
 
@@ -767,6 +768,12 @@ module Hobo::Dryml
767
768
  @gensym_counter += 1
768
769
  "#{name}_#{@gensym_counter}"
769
770
  end
771
+
772
+ def rename_class(name)
773
+ name = name[1..-2]
774
+ name = class_renames[name] while class_renames.has_key?(name)
775
+ name
776
+ end
770
777
 
771
778
  end
772
779
 
@@ -31,7 +31,7 @@ module Hobo
31
31
  end
32
32
 
33
33
  def inspect
34
- "#<EnumString #{(values || []) * ' '}>"
34
+ name.blank? ? "#<EnumString #{(values || []) * ' '}>" : name
35
35
  end
36
36
  alias_method :to_s, :inspect
37
37
 
@@ -16,6 +16,13 @@ module Hobo
16
16
  def field(name, *args)
17
17
  type = args.shift
18
18
  options = args.extract_options!
19
+
20
+ @model.name_attribute = name.to_sym if options.delete(:name)
21
+ @model.primary_content_attribute = name.to_sym if options.delete(:description)
22
+ @model.creator_attribute = name.to_sym if options.delete(:creator)
23
+
24
+ @model.send(:login_attribute=, name.to_sym, options.delete(:validate)) if @model < User && options.delete(:login)
25
+
19
26
  @model.send(:set_field_type, name => type) unless
20
27
  type.in?(@model.connection.native_database_types.keys - [:text])
21
28
  @model.field_specs[name] = FieldSpec.new(@model, name, type, options)
@@ -15,6 +15,10 @@ module Hobo
15
15
  def super_user?
16
16
  false
17
17
  end
18
+
19
+ def administrator?
20
+ false
21
+ end
18
22
 
19
23
  end
20
24
 
@@ -54,8 +54,8 @@ module Hobo
54
54
  # TODO - what if you want if_available as a query param?
55
55
  if_available = params.delete(:if_available)
56
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)))
57
+ ((action.nil? && obj.respond_to?(:typed_id) && !linkable?(obj.class, :show, :subsite => subsite)) ||
58
+ (action.nil? && obj.is_a?(Class) && !linkable?(obj, :index, :subsite => subsite)))
59
59
 
60
60
  base = subsite.blank? ? base_url : "/#{subsite}#{base_url}"
61
61
 
@@ -195,7 +195,11 @@ module Hobo
195
195
 
196
196
  def can_edit?(*args)
197
197
  if args.empty?
198
- this_parent && this_field && can_edit?(this_parent, this_field)
198
+ if this_parent && this_field
199
+ can_edit?(this_parent, this_field)
200
+ else
201
+ can_edit?(this, nil)
202
+ end
199
203
  else
200
204
  object, field = args.length == 2 ? args : [this, args.first]
201
205
 
@@ -300,10 +304,11 @@ module Hobo
300
304
  end
301
305
 
302
306
 
303
- def create_model(model)
304
- n = model.new
305
- n.set_creator(current_user)
306
- n
307
+ def new_for_current_user(model_or_assoc=nil)
308
+ model_or_assoc ||= this
309
+ record = model_or_assoc.new
310
+ record.set_creator(current_user)
311
+ record
307
312
  end
308
313
 
309
314
 
@@ -356,11 +361,34 @@ module Hobo
356
361
  end
357
362
  end
358
363
 
359
- def linkable?(obj, action, subsite=self.subsite)
360
- Hobo::ModelRouter.linkable?(subsite, obj, action)
364
+ def linkable?(*args)
365
+ options = args.extract_options!
366
+ target = args.empty? || args.first.is_a?(Symbol) ? this : args.shift
367
+ action = args.first
368
+
369
+ if target.is_a?(Class)
370
+ klass = target
371
+ action ||= :index
372
+ elsif target.respond_to?(:member_class)
373
+ klass = target.member_class
374
+ action ||= :show
375
+ else
376
+ klass = target.class
377
+ action ||= :show
378
+ end
379
+
380
+ Hobo::ModelRouter.linkable?(subsite, klass, action.to_sym)
361
381
  end
362
382
 
363
383
 
384
+ # Convenience helper for the default app
385
+
386
+ def front_models
387
+ Hobo.models.select {|m| linkable?(m) && !(m < Hobo::User)}
388
+ end
389
+
390
+
391
+
364
392
  # debugging support
365
393
 
366
394
  def abort_with(*args)