hobo 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/bin/hobo +24 -7
  2. data/hobo_files/plugin/CHANGES.txt +501 -0
  3. data/hobo_files/plugin/generators/hobo/hobo_generator.rb +8 -6
  4. data/hobo_files/plugin/generators/hobo/templates/application.dryml +3 -0
  5. data/hobo_files/plugin/generators/hobo/templates/dryml-support.js +132 -0
  6. data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +4 -5
  7. data/hobo_files/plugin/generators/hobo_model_resource/hobo_model_resource_generator.rb +75 -0
  8. data/hobo_files/plugin/generators/hobo_model_resource/templates/controller.rb +7 -0
  9. data/hobo_files/plugin/generators/hobo_model_resource/templates/functional_test.rb +8 -0
  10. data/hobo_files/plugin/generators/hobo_model_resource/templates/helper.rb +2 -0
  11. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.js +30 -11
  12. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +149 -92
  13. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +0 -48
  14. data/hobo_files/plugin/init.rb +45 -13
  15. data/hobo_files/plugin/lib/action_view_extensions/base.rb +4 -3
  16. data/hobo_files/plugin/lib/active_record/association_proxy.rb +18 -0
  17. data/hobo_files/plugin/lib/active_record/association_reflection.rb +5 -0
  18. data/hobo_files/plugin/lib/active_record/has_many_association.rb +7 -11
  19. data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +8 -0
  20. data/hobo_files/plugin/lib/extensions/test_case.rb +1 -1
  21. data/hobo_files/plugin/lib/hobo.rb +38 -60
  22. data/hobo_files/plugin/lib/hobo/authentication_support.rb +1 -1
  23. data/hobo_files/plugin/lib/hobo/bundle.rb +131 -34
  24. data/hobo_files/plugin/lib/hobo/composite_model.rb +1 -1
  25. data/hobo_files/plugin/lib/hobo/controller.rb +7 -8
  26. data/hobo_files/plugin/lib/hobo/dev_controller.rb +21 -0
  27. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +14 -8
  28. data/hobo_files/plugin/lib/hobo/dryml/dryml_support_controller.rb +13 -0
  29. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +6 -7
  30. data/hobo_files/plugin/lib/hobo/dryml/template.rb +207 -73
  31. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +67 -55
  32. data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +53 -3
  33. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +75 -107
  34. data/hobo_files/plugin/lib/hobo/model.rb +236 -429
  35. data/hobo_files/plugin/lib/hobo/model_controller.rb +277 -437
  36. data/hobo_files/plugin/lib/hobo/model_router.rb +62 -29
  37. data/hobo_files/plugin/lib/hobo/rapid_helper.rb +48 -9
  38. data/hobo_files/plugin/lib/hobo/scopes.rb +98 -0
  39. data/hobo_files/plugin/lib/hobo/scopes/association_proxy_extensions.rb +31 -0
  40. data/hobo_files/plugin/lib/hobo/scopes/automatic_scopes.rb +282 -0
  41. data/hobo_files/plugin/lib/hobo/scopes/defined_scope_proxy_extender.rb +88 -0
  42. data/hobo_files/plugin/lib/hobo/scopes/scope_reflection.rb +18 -0
  43. data/hobo_files/plugin/lib/hobo/scopes/scoped_proxy.rb +59 -0
  44. data/hobo_files/plugin/lib/hobo/undefined.rb +2 -0
  45. data/hobo_files/plugin/lib/hobo/user.rb +31 -14
  46. data/hobo_files/plugin/lib/hobo/user_controller.rb +41 -27
  47. data/hobo_files/plugin/taglibs/core.dryml +9 -11
  48. data/hobo_files/plugin/taglibs/rapid.dryml +51 -108
  49. data/hobo_files/plugin/taglibs/rapid_editing.dryml +25 -25
  50. data/hobo_files/plugin/taglibs/rapid_forms.dryml +111 -79
  51. data/hobo_files/plugin/taglibs/rapid_generics.dryml +74 -0
  52. data/hobo_files/plugin/taglibs/rapid_navigation.dryml +23 -21
  53. data/hobo_files/plugin/taglibs/rapid_pages.dryml +83 -169
  54. data/hobo_files/plugin/taglibs/rapid_plus.dryml +16 -2
  55. data/hobo_files/plugin/taglibs/rapid_support.dryml +3 -3
  56. data/hobo_files/plugin/taglibs/rapid_user_pages.dryml +104 -0
  57. metadata +60 -55
  58. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +0 -276
  59. data/hobo_files/plugin/generators/hobo_migration/templates/migration.rb +0 -9
  60. data/hobo_files/plugin/lib/active_record/table_definition.rb +0 -34
  61. data/hobo_files/plugin/lib/extensions.rb +0 -375
  62. data/hobo_files/plugin/lib/hobo/email_address.rb +0 -12
  63. data/hobo_files/plugin/lib/hobo/enum_string.rb +0 -50
  64. data/hobo_files/plugin/lib/hobo/field_declaration_dsl.rb +0 -43
  65. data/hobo_files/plugin/lib/hobo/field_spec.rb +0 -68
  66. data/hobo_files/plugin/lib/hobo/html_string.rb +0 -7
  67. data/hobo_files/plugin/lib/hobo/lazy_hash.rb +0 -40
  68. data/hobo_files/plugin/lib/hobo/markdown_string.rb +0 -11
  69. data/hobo_files/plugin/lib/hobo/migrations.rb +0 -12
  70. data/hobo_files/plugin/lib/hobo/model_queries.rb +0 -117
  71. data/hobo_files/plugin/lib/hobo/password_string.rb +0 -7
  72. data/hobo_files/plugin/lib/hobo/percentage.rb +0 -14
  73. data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +0 -78
  74. data/hobo_files/plugin/lib/hobo/proc_binding.rb +0 -32
  75. data/hobo_files/plugin/lib/hobo/text.rb +0 -3
  76. data/hobo_files/plugin/lib/hobo/textile_string.rb +0 -25
  77. data/hobo_files/plugin/lib/hobo/where_fragment.rb +0 -28
@@ -52,12 +52,45 @@ module Hobo::Dryml
52
52
  attr_accessor
53
53
 
54
54
  for attr in [:erb_binding, :part_contexts, :view_name,
55
- :this, :this_parent, :this_field, :this_type,
55
+ :this, :this_parent, :this_field,
56
56
  :form_field_path, :form_this, :form_field_names]
57
57
  class_eval "def #{attr}; @_#{attr}; end"
58
58
  end
59
59
 
60
60
 
61
+ # The type of this, or when this is nil, the type that would be expected in the current field
62
+ def this_type
63
+ @_this_type ||= if this == false || this == true
64
+ Hobo::Boolean
65
+ elsif this
66
+ this.class
67
+ elsif this_parent && this_field && (parent_class = this_parent.class).respond_to?(:attr_type)
68
+ type = parent_class.attr_type(this_field)
69
+ if type.is_a?(ActiveRecord::Reflection::AssociationReflection)
70
+ reflection = type
71
+ if reflection.macro == :has_many
72
+ Array
73
+ elsif reflection.options[:polymorphic]
74
+ # All we know is that it will be some active-record type
75
+ ActiveRecord::Base
76
+ else
77
+ reflection.klass
78
+ end
79
+ else
80
+ type
81
+ end
82
+ else
83
+ # Nothing to go on at all
84
+ Object
85
+ end
86
+ end
87
+
88
+
89
+ def this_field_reflection
90
+ this_parent && this_field && this_parent.class.respond_to?(:reflections) && this_parent.class.reflections[this_field.to_sym]
91
+ end
92
+
93
+
61
94
  def attrs_for(name)
62
95
  self.class.tag_attrs[name.to_sym]
63
96
  end
@@ -95,51 +128,50 @@ module Hobo::Dryml
95
128
  end
96
129
 
97
130
 
98
- def this_field_dom_id
99
- if this_parent && this_field
100
- Hobo.dom_id(this_parent, this_field)
101
- else
102
- Hobo.dom_id(this)
131
+ def dom_id(object=nil, attribute=nil)
132
+ if object.nil?
133
+ # nothing passed -- use context
134
+ if this_parent && this_field
135
+ object, attribute = this_parent, this_field
136
+ else
137
+ object = this
138
+ end
103
139
  end
104
- end
105
-
106
-
107
- def context_id
108
- if this_parent and this_parent.is_a?(ActiveRecord::Base) and this_field
109
- this_field_dom_id
110
- elsif this.respond_to?(:typed_id)
111
- this.typed_id
112
- elsif this.is_a?(Array) and !this.respond_to?(:proxy_reflection)
113
- "nil"
140
+
141
+ id = object.try.typed_id
142
+ if id
143
+ attribute ? "#{id}_#{attribute}" : id
114
144
  else
115
- Hobo.dom_id(this)
145
+ "nil"
116
146
  end
117
147
  end
118
-
119
148
 
120
- def call_part(dom_id, part_name, part_this=nil, *locals)
149
+
150
+ def call_part(part_node_id, part_name, part_this=nil, *locals)
121
151
  res = ''
122
152
  if part_this
123
153
  new_object_context(part_this) do
124
- @_part_contexts[dom_id] = PartContext.new(part_name, context_id, locals)
154
+ @_part_contexts[part_node_id] = PartContext.new(part_name, dom_id, locals)
125
155
  res = send("#{part_name}_part", *locals)
126
156
  end
127
157
  else
128
158
  new_context do
129
- @_part_contexts[dom_id] = PartContext.new(part_name, context_id, locals)
159
+ @_part_contexts[part_node_id] = PartContext.new(part_name, dom_id, locals)
130
160
  res = send("#{part_name}_part", *locals)
131
161
  end
132
162
  end
133
163
  res
134
164
  end
165
+
135
166
 
136
167
  def call_polymorphic_tag(name, *args)
168
+ name = name.to_s.gsub('-', '_')
137
169
  type = args.first.is_a?(Class) ? args.shift : nil
138
170
  attributes, parameters = args
139
171
 
140
172
  tag = find_polymorphic_tag(name, type)
141
173
  if tag != name
142
- send(tag, attributes, parameters || {})
174
+ send(tag, attributes || {}, parameters || {})
143
175
  else
144
176
  nil
145
177
  end
@@ -147,18 +179,7 @@ module Hobo::Dryml
147
179
 
148
180
 
149
181
  def find_polymorphic_tag(name, call_type=nil)
150
- call_type ||= case this_type
151
- when ActiveRecord::Reflection::AssociationReflection
152
- # Don't blow up with non-existent polymorphic types
153
- return name if this_type.options[:polymorphic] && !Object.const_defined?(this_type.class_name)
154
- this_type.klass
155
- when Array
156
- this.member_class
157
- else
158
- this_type
159
- end
160
-
161
- call_type = TrueClass if call_type == FalseClass
182
+ call_type ||= (this.is_a?(Array) && this.respond_to?(:member_class) && this.try.member_class) || this_type
162
183
 
163
184
  while true
164
185
  if call_type == ActiveRecord::Base || call_type == Object
@@ -192,8 +213,9 @@ module Hobo::Dryml
192
213
  def new_context
193
214
  ctx = [ @_erb_output,
194
215
  @_this, @_this_parent, @_this_field, @_this_type,
195
- @_form_field_path]
216
+ @_form_field_path ]
196
217
  @_erb_output = ""
218
+ @_this_type = nil
197
219
  res = yield
198
220
  @_erb_output, @_this, @_this_parent, @_this_field, @_this_type, @_form_field_path = ctx
199
221
  res.to_s
@@ -202,14 +224,7 @@ module Hobo::Dryml
202
224
 
203
225
  def new_object_context(new_this)
204
226
  new_context do
205
- @_this_parent,@_this_field,@_this_type = if new_this.respond_to?(:proxy_reflection)
206
- refl = new_this.proxy_reflection
207
- [new_this.proxy_owner, refl.name, refl]
208
- else
209
- # In dryml, TrueClass is the 'boolean' class
210
- t = new_this.class == FalseClass ? TrueClass : new_this.class
211
- [nil, nil, t]
212
- end
227
+ @_this_parent, @_this_field = [new_this.origin, new_this.origin_attribute] if new_this.respond_to?(:origin)
213
228
  @_this = new_this
214
229
  yield
215
230
  end
@@ -226,17 +241,7 @@ module Hobo::Dryml
226
241
  [field_path]
227
242
  end
228
243
  parent, field, obj = Hobo.get_field_path(tag_this || this, path)
229
-
230
- type = if parent.class.respond_to?(:field_type) && field_type = parent.class.field_type(field)
231
- field_type
232
- elsif obj == false
233
- # In dryml, TrueClass is the 'boolean' class
234
- TrueClass
235
- else
236
- obj.class
237
- end
238
-
239
- @_this, @_this_parent, @_this_field, @_this_type = obj, parent, field, type
244
+ @_this, @_this_parent, @_this_field = obj, parent, field
240
245
  @_form_field_path += path if @_form_field_path
241
246
  yield
242
247
  end
@@ -432,7 +437,14 @@ module Hobo::Dryml
432
437
  def render_tag(tag_name, attributes)
433
438
  method_name = tag_name.gsub('-', '_')
434
439
  if respond_to?(method_name)
435
- (send(method_name, attributes) + part_contexts_storage_tag).strip
440
+ res = (send(method_name, attributes) + part_contexts_storage_tag).strip
441
+
442
+ # TODO: Temporary hack to get the dryml metadata comments in the right place
443
+ if RAILS_ENV == "development"
444
+ res.gsub(/^(.*?)(<!DOCTYPE.*?>).*?(<html.*?>)/m, "\\2\\3\\1")
445
+ else
446
+ res
447
+ end
436
448
  else
437
449
  false
438
450
  end
@@ -8,12 +8,62 @@ module Hobo::Dryml
8
8
 
9
9
  def render(src, local_assigns)
10
10
  renderer = Hobo::Dryml.page_renderer(@view, local_assigns.keys)
11
- s = renderer.render_page(@view.assigns["this"] || local_assigns[:this], local_assigns)
12
- # Important to strip whitespace, or the browser hangs around for ages (FF2)
11
+ this = @view.instance_variable_set("@this", @view.controller.send(:dryml_context) || local_assigns[:this])
12
+ s = renderer.render_page(this, local_assigns)
13
13
 
14
- s.strip
14
+ # Important to strip whitespace, or the browser hangs around for ages (FF2)
15
+ s = s.strip
16
+
17
+ # TODO: Temporary hack to get the dryml metadata comments in the right place
18
+ if RAILS_ENV == "development"
19
+ s.gsub(/^(.*?)(<!DOCTYPE.*?>).*?(<html.*?>)/m, "\\2\\3\\1")
20
+ else
21
+ s
22
+ end
15
23
  end
16
24
 
17
25
  end
18
26
 
19
27
  end
28
+
29
+ module ActionController
30
+
31
+
32
+ class Base
33
+
34
+ def dryml_context
35
+ @this
36
+ end
37
+
38
+ def dryml_fallback_tag(tag_name)
39
+ @dryml_fallback_tag = tag_name
40
+ end
41
+
42
+ def render_tag(tag, options={}, render_options={})
43
+ add_variables_to_assigns
44
+
45
+ if options[:with]
46
+ @this = options[:with] unless options[:field]
47
+ else
48
+ options[:with] = dryml_context
49
+ end
50
+
51
+ text = Hobo::Dryml.render_tag(@template, tag, options)
52
+ text && render({:text => text, :layout => false }.merge(render_options))
53
+ end
54
+
55
+ def render_for_file_with_dryml(template_path, *args)
56
+ if template_path !~ /^\// && # not an absolute path (e.g. an exception ERB template)
57
+ !template_exists?(template_path) && # no template available in app/views
58
+ tag_name = @dryml_fallback_tag || "#{File.basename(template_path).dasherize}-page"
59
+
60
+ # The template was missing, try to use a DRYML <page> tag instead
61
+ render_tag(tag_name) or raise ActionController::MissingTemplate, "Missing template #{template_path}.html.erb in view path #{RAILS_ROOT}/app/views"
62
+ else
63
+ render_for_file_without_dryml(template_path, *args)
64
+ end
65
+ end
66
+ alias_method_chain :render_for_file, :dryml
67
+
68
+ end
69
+ end
@@ -40,66 +40,51 @@ module Hobo
40
40
  def subsite
41
41
  params[:controller].match(/([^\/]+)\//)._?[1]
42
42
  end
43
+
44
+
45
+ IMPLICIT_ACTIONS = [:index, :show, :create, :update, :destroy]
43
46
 
44
-
45
- def object_url(*args)
47
+ def object_url(obj, *args)
46
48
  params = args.extract_options!
47
- obj, action = args
48
- action &&= action.to_s
49
-
50
- controller_name = controller_for(obj)
51
-
52
- subsite = params[:subsite] || self.subsite
49
+ action = args.first._?.to_sym
50
+ options, params = params.partition_hash([:subsite, :method, :format])
51
+ options[:subsite] ||= self.subsite
53
52
 
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 => subsite)) ||
58
- (action.nil? && obj.is_a?(Class) && !linkable?(obj, :index, :subsite => subsite)))
59
-
60
- base = subsite.blank? ? base_url : "/#{subsite}#{base_url}"
61
-
62
- parts = if obj.is_a? Class
63
- [base, controller_name]
64
-
65
- elsif obj.is_a? Hobo::CompositeModel
66
- [base, controller_name, obj.to_param]
67
-
68
- elsif obj.is_a? ActiveRecord::Base
69
- if obj.new_record?
70
- [base, controller_name]
71
- else
72
- raise HoboError.new("invalid object url: new for existing object") if action == "new"
73
-
74
- klass = obj.class
75
- id = if klass.id_name?
76
- obj.id_name(true)
77
- else
78
- obj.to_param
79
- end
80
-
81
- [base, controller_name, id]
82
- end
83
-
84
- elsif obj.is_a? Array # warning - this breaks if we use `case/when Array`
85
- owner = obj.proxy_owner
86
- new_model = obj.proxy_reflection.klass
87
- [object_url(owner), obj.proxy_reflection.name]
88
-
89
- else
90
- raise HoboError.new("cannot create url for #{obj.inspect} (#{obj.class})")
91
- end
92
- url = parts.join("/")
53
+ if obj.respond_to?(:origin)
54
+ # Asking for URL of a collection, e.g. category/1/adverts or category/1/adverts/new
55
+ if action == :new
56
+ action_path = "#{obj.origin_attribute}/new"
57
+ action = "new_#{obj.origin_attribute.to_s.singularize}"
58
+ elsif action.nil?
59
+ action = obj.origin_attribute
60
+ end
61
+ obj = obj.origin
62
+
63
+ else
64
+ action ||= case options[:method].to_s
65
+ when 'put'; :update
66
+ when 'post'; :create
67
+ when 'delete'; :destroy
68
+ else; obj.is_a?(Class) ? :index : :show
69
+ end
93
70
 
94
- case action
95
- when nil # do nothing
96
- when "destroy" then params["_method"] = "DELETE"
97
- when "update" then params["_method"] = "PUT"
98
- else url += "/#{action}"
71
+ if action == :create && obj.try.new_record?
72
+ # Asking for url to post new record to
73
+ obj = obj.class
74
+ end
99
75
  end
76
+
77
+ klass = obj.is_a?(Class) ? obj : obj.class
78
+ if Hobo::ModelRouter.linkable?(klass, action, options)
79
+
80
+ path = obj.to_url_path or HoboError.new("cannot create url for #{obj.inspect} (#{obj.class})")
81
+ url = "#{base_url}#{'/' + subsite unless subsite.blank?}/#{path}"
100
82
 
101
- params = make_params(params - [:subsite])
102
- params.blank? ? url : "#{url}?#{params}"
83
+ url += "/#{action_path || action}" unless action.in?(IMPLICIT_ACTIONS)
84
+
85
+ params = make_params(params)
86
+ params.blank? ? url : "#{url}?#{params}"
87
+ end
103
88
  end
104
89
 
105
90
 
@@ -127,31 +112,16 @@ module Hobo
127
112
  hash.map {|k,v| _as_params(k, v)}.join("&")
128
113
  end
129
114
 
130
-
131
- def dom_id(*args)
132
- if args.length == 0
133
- Hobo.dom_id(this)
134
- else
135
- Hobo.dom_id(*args)
136
- end
137
- rescue ArgumentError
138
- ""
139
- end
140
-
141
115
 
142
116
  def type_id(type=nil)
143
- type ||= this.is_a?(Class) ? this : this_type
144
- type == NilClass ? "" : Hobo.type_id(type || this.class)
117
+ type ||= (this.is_a?(Class) && this) || this_type || this.class
118
+ HoboFields.to_name(type) || type.name.underscore.gsub("/", "__")
145
119
  end
146
-
120
+
147
121
 
148
122
  def type_and_field(*args)
149
- if args.empty?
150
- this_parent && this_field && "#{Hobo.type_id(this_parent.class)}_#{this_field}"
151
- else
152
- type, field = args
153
- "#{Hobo.type_id(type)}_#{field}"
154
- end
123
+ type, field = args.empty? ? [this_parent.class, this_field] : args
124
+ "#{type.typed_id}_#{field}" if type.respond_to?(:typed_id)
155
125
  end
156
126
 
157
127
 
@@ -203,8 +173,8 @@ module Hobo
203
173
  else
204
174
  object, field = args.length == 2 ? args : [this, args.first]
205
175
 
206
- if !field and object.respond_to?(:proxy_reflection)
207
- Hobo.can_edit?(current_user, object.proxy_owner, object.proxy_reflection.name)
176
+ if !field && object.respond_to?(:origin)
177
+ Hobo.can_edit?(current_user, object.origin, object.origin_attribute)
208
178
  else
209
179
  Hobo.can_edit?(current_user, object, field)
210
180
  end
@@ -225,12 +195,14 @@ module Hobo
225
195
  object = this
226
196
  end
227
197
  end
228
-
229
- if !field and object.respond_to?(:proxy_reflection)
230
- Hobo.can_view?(current_user, object.proxy_owner, object.proxy_reflection.name)
231
- else
232
- Hobo.can_view?(current_user, object, field)
233
- end
198
+
199
+ @can_view_cache ||= {}
200
+ @can_view_cache[ [object, field] ] ||=
201
+ if !field && object.respond_to?(:origin)
202
+ Hobo.can_view?(current_user, object.origin, object.origin_attribute)
203
+ else
204
+ Hobo.can_view?(current_user, object, field)
205
+ end
234
206
  end
235
207
 
236
208
 
@@ -272,8 +244,8 @@ module Hobo
272
244
 
273
245
  def param_name_for_this(foreign_key=false)
274
246
  return "" unless form_this
275
- name = if foreign_key and this_type.respond_to?(:macro) and this_type.macro == :belongs_to
276
- param_name_for(form_this, form_field_path[0..-2] + [this_type.primary_key_name])
247
+ name = if foreign_key && (refl = this_field_reflection) && refl.macro == :belongs_to
248
+ param_name_for(form_this, form_field_path[0..-2] + [refl.primary_key_name])
277
249
  else
278
250
  param_name_for(form_this, form_field_path)
279
251
  end
@@ -282,21 +254,10 @@ module Hobo
282
254
  end
283
255
 
284
256
 
285
- def selector_type
286
- if this.is_a? ActiveRecord::Base
287
- this.class
288
- elsif this.respond_to? :member_class
289
- this.member_class
290
- elsif this == @this
291
- @model
292
- end
293
- end
294
-
295
-
296
257
  def transpose_with_field(field, collection=nil)
297
258
  collection ||= this
298
259
  matrix = collection.map {|obj| obj.send(field) }
299
- max_length = matrix.every(:length).max
260
+ max_length = matrix.*.length.max
300
261
  matrix = matrix.map do |a|
301
262
  a + [nil] * (max_length - a.length)
302
263
  end
@@ -306,9 +267,7 @@ module Hobo
306
267
 
307
268
  def new_for_current_user(model_or_assoc=nil)
308
269
  model_or_assoc ||= this
309
- record = model_or_assoc.new
310
- record.set_creator(current_user)
311
- record
270
+ model_or_assoc.user_new(current_user)
312
271
  end
313
272
 
314
273
 
@@ -338,8 +297,12 @@ module Hobo
338
297
 
339
298
 
340
299
  # Sign-up url for a given user record or user class
341
- def signup_url(user_or_class)
342
- c = user_or_class.is_a?(Class) ? user_or_class : user_or_class.class
300
+ def signup_url(user_or_class=nil)
301
+ c = case user_or_class
302
+ when Class; user_or_class
303
+ when nil; Hobo::User.default_user_model
304
+ else user_or_class
305
+ end
343
306
  send("#{c.name.underscore}_signup_url") rescue nil
344
307
  end
345
308
 
@@ -366,23 +329,28 @@ module Hobo
366
329
  target = args.empty? || args.first.is_a?(Symbol) ? this : args.shift
367
330
  action = args.first
368
331
 
369
- if target.is_a?(Class)
332
+ if (origin = target.try.origin)
333
+ klass = origin.class
334
+ action = if action == :new
335
+ "new_#{target.origin_attribute.to_s.singularize}"
336
+ elsif action.nil?
337
+ target.origin_attribute
338
+ end
339
+ elsif target.is_a?(Class)
370
340
  klass = target
371
341
  action ||= :index
372
- elsif target.respond_to?(:member_class)
373
- klass = target.member_class
374
- action ||= :show
375
342
  else
376
343
  klass = target.class
377
344
  action ||= :show
378
345
  end
379
346
 
380
- Hobo::ModelRouter.linkable?(subsite, klass, action.to_sym)
347
+ Hobo::ModelRouter.linkable?(klass, action, options.reverse_merge(:subsite => subsite))
381
348
  end
382
349
 
383
350
 
384
351
  # Convenience helper for the default app
385
352
 
353
+ # FIXME: this should interrogate the routes to find index methods, not the models
386
354
  def front_models
387
355
  Hobo.models.select {|m| linkable?(m) && !(m < Hobo::User)}
388
356
  end
@@ -398,7 +366,7 @@ module Hobo
398
366
  def log_debug(*args)
399
367
  logger.debug("\n### DRYML Debug ###")
400
368
  logger.debug(args.map {|a| PP.pp(a, "")}.join("-------\n"))
401
- logger.debug("DRYML THIS = #{Hobo.dom_id(this) rescue this.inspect}")
369
+ logger.debug("DRYML THIS = #{this.typed_id rescue this.inspect}")
402
370
  logger.debug("###################\n")
403
371
  args.first unless args.empty?
404
372
  end