hobo 0.6 → 0.6.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 (39) hide show
  1. data/bin/hobo +2 -3
  2. data/hobo_files/plugin/CHANGES.txt +139 -0
  3. data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +1 -8
  4. data/hobo_files/plugin/generators/hobo_front_controller/templates/controller.rb +1 -39
  5. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +2 -2
  6. data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +27 -7
  7. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +1 -2
  8. data/hobo_files/plugin/generators/hobo_user_controller/USAGE +34 -0
  9. data/hobo_files/plugin/generators/hobo_user_controller/hobo_user_controller_generator.rb +43 -0
  10. data/hobo_files/plugin/generators/hobo_user_controller/templates/controller.rb +5 -0
  11. data/hobo_files/plugin/generators/hobo_user_controller/templates/functional_test.rb +18 -0
  12. data/hobo_files/plugin/generators/hobo_user_controller/templates/helper.rb +2 -0
  13. data/hobo_files/plugin/generators/hobo_user_controller/templates/view.rhtml +2 -0
  14. data/hobo_files/plugin/init.rb +6 -2
  15. data/hobo_files/plugin/lib/extensions.rb +28 -41
  16. data/hobo_files/plugin/lib/hobo.rb +37 -17
  17. data/hobo_files/plugin/lib/hobo/authentication_support.rb +25 -10
  18. data/hobo_files/plugin/lib/hobo/composite_model.rb +2 -2
  19. data/hobo_files/plugin/lib/hobo/controller.rb +8 -34
  20. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +1 -1
  21. data/hobo_files/plugin/lib/hobo/dryml/part_context.rb +103 -0
  22. data/hobo_files/plugin/lib/hobo/dryml/template.rb +10 -11
  23. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +29 -72
  24. data/hobo_files/plugin/lib/hobo/hobo_helper.rb +11 -10
  25. data/hobo_files/plugin/lib/hobo/migrations.rb +12 -0
  26. data/hobo_files/plugin/lib/hobo/model.rb +3 -3
  27. data/hobo_files/plugin/lib/hobo/model_controller.rb +3 -3
  28. data/hobo_files/plugin/lib/hobo/rapid_helper.rb +3 -3
  29. data/hobo_files/plugin/lib/hobo/user_controller.rb +80 -0
  30. data/hobo_files/plugin/tags/rapid.dryml +36 -20
  31. data/hobo_files/plugin/tags/rapid_editing.dryml +4 -5
  32. data/hobo_files/plugin/tags/rapid_forms.dryml +6 -6
  33. data/hobo_files/plugin/tags/rapid_navigation.dryml +7 -5
  34. data/hobo_files/plugin/tags/rapid_pages.dryml +116 -10
  35. data/hobo_files/plugin/tags/rapid_support.dryml +23 -0
  36. metadata +13 -5
  37. data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +0 -42
  38. data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +0 -43
  39. data/hobo_files/plugin/lib/hobo/mapping_tags.rb +0 -262
@@ -258,10 +258,6 @@ module Hobo::Dryml
258
258
  dryml_exception("def cannot have both alias_of and alias_current_as", el) if alias_of && alias_current
259
259
  dryml_exception("def with alias_of must be empty", el) if alias_of and el.size > 0
260
260
 
261
- # If we're redefining, we need a statement in the method body
262
- # that does the alias_method on the fly.
263
- re_alias = ""
264
-
265
261
  if alias_of || alias_current
266
262
  old_name = alias_current ? name : alias_of
267
263
  new_name = alias_current ? alias_current : name
@@ -270,12 +266,12 @@ module Hobo::Dryml
270
266
  end
271
267
 
272
268
  res = if alias_of
273
- "#{re_alias}<% #{tag_newlines(el)} %>"
269
+ "<% #{tag_newlines(el)} %>"
274
270
  else
275
271
  src = if template_name?(name)
276
- template_method(name, re_alias, el)
272
+ template_method(name, el)
277
273
  else
278
- tag_method(name, re_alias, el)
274
+ tag_method(name, el)
279
275
  end
280
276
  src << "<% _register_tag_attrs(:#{name}, #{declared_attributes(el).inspect}) %>"
281
277
 
@@ -312,7 +308,7 @@ module Hobo::Dryml
312
308
  end
313
309
 
314
310
 
315
- def template_method(name, re_alias, el)
311
+ def template_method(name, el)
316
312
  param_names = param_names_in_template(el)
317
313
 
318
314
  "<% def #{name}(all_attributes={}, all_parameters={}, &__block__); " +
@@ -322,7 +318,7 @@ module Hobo::Dryml
322
318
  end
323
319
 
324
320
 
325
- def tag_method(name, re_alias, el)
321
+ def tag_method(name, el)
326
322
  "<% def #{name}(all_attributes={}, &__block__); " +
327
323
  "parameters = nil; " +
328
324
  tag_method_body(el) +
@@ -386,13 +382,16 @@ module Hobo::Dryml
386
382
  part_name = el.attributes['part']
387
383
  dom_id = el.attributes['id'] || part_name
388
384
 
389
- part_src = "<% def #{part_name}_part #{tag_newlines(el)}; new_context do %>" +
385
+ part_locals = el.attributes["part_locals"]
386
+
387
+ part_src = "<% def #{part_name}_part(#{part_locals}) #{tag_newlines(el)}; new_context do %>" +
390
388
  content +
391
389
  "<% end; end %>"
392
390
  @builder.add_part(part_name, restore_erb_scriptlets(part_src), element_line_num(el))
393
391
 
394
392
  newlines = "\n" * part_src.count("\n")
395
- "<%= call_part(#{attribute_to_ruby(dom_id)}, :#{part_name}) #{newlines} %>"
393
+ args = [attribute_to_ruby(dom_id), ":#{part_name}", "nil", part_locals].compact
394
+ "<%= call_part(#{args * ', '}) #{newlines} %>"
396
395
  end
397
396
 
398
397
 
@@ -7,61 +7,13 @@ module Hobo::Dryml
7
7
  subclass.compiled_local_names = []
8
8
  end
9
9
  attr_accessor :load_time, :compiled_local_names
10
-
11
- # --- Local Tags --- #
12
-
13
- def start_redefine_block(method_names)
14
- @_preserved_methods_for_redefine ||= []
15
- @_redef_impl_names ||= []
16
-
17
- methods = {}
18
- method_names.each {|m| methods[m] = m.in?(self.methods) && instance_method(m) }
19
- @_preserved_methods_for_redefine.push(methods)
20
- @_redef_impl_names.push []
21
- end
22
-
23
-
24
- def end_redefine_block
25
- methods = @_preserved_methods_for_redefine.pop
26
- methods.each_pair do |name, method|
27
- if method
28
- define_method(name, method)
29
- else
30
- remove_method(name)
31
- end
32
- end
33
- to_remove = @_redef_impl_names.pop
34
- to_remove.each {|m| remove_method(m) }
35
- end
36
-
37
-
38
- def redefine_nesting
39
- @_preserved_methods_for_redefine.length
40
- end
41
-
42
-
43
- def redefine_tag(name, proc)
44
- impl_name = "#{name}_redefined_#{redefine_nesting}"
45
- define_method(impl_name, proc)
46
- class_eval "def #{name}(options={}, &b); #{impl_name}(options, b); end"
47
- @_redef_impl_names.push(impl_name)
48
- end
49
-
50
- def redefine_template(name, proc)
51
- impl_name = "#{name}_redefined_#{redefine_nesting}"
52
- define_method(impl_name, proc)
53
- class_eval "def #{name}(options={}, template_parameters={}, &b); " +
54
- "#{impl_name}(options, template_parameters, b); end"
55
- @_redef_impl_names.push(impl_name)
56
- end
57
-
58
- # --- end local tags --- #
59
-
10
+
60
11
 
61
12
  def _register_tag_attrs(tag_name, attrs)
62
13
  @tag_attrs ||= {}
63
14
  @tag_attrs[tag_name] = attrs
64
15
  end
16
+
65
17
 
66
18
  def tag_attrs
67
19
  @tag_attrs ||= {}
@@ -123,6 +75,7 @@ module Hobo::Dryml
123
75
 
124
76
 
125
77
  def merge_attrs(attrs, overriding_attrs)
78
+ return {}.update(attrs) if overriding_attrs.nil?
126
79
  attrs = attrs.with_indifferent_access unless attrs.is_a?(HashWithIndifferentAccess)
127
80
  classes = overriding_attrs[:class]
128
81
  attrs = add_classes(attrs, *classes.split) if classes
@@ -148,8 +101,8 @@ module Hobo::Dryml
148
101
  end
149
102
  end
150
103
 
151
-
152
- def part_context_model_id
104
+
105
+ def context_id
153
106
  if this_parent and this_parent.is_a?(ActiveRecord::Base) and this_field
154
107
  this_field_dom_id
155
108
  elsif this.respond_to?(:typed_id)
@@ -161,18 +114,18 @@ module Hobo::Dryml
161
114
  end
162
115
  end
163
116
 
164
-
165
- def call_part(dom_id, part_id, part_this=nil)
117
+
118
+ def call_part(dom_id, part_name, part_this=nil, *locals)
166
119
  res = ''
167
120
  if part_this
168
121
  new_object_context(part_this) do
169
- @_part_contexts[dom_id] = [part_id, part_context_model_id]
170
- res = send("#{part_id}_part")
122
+ @_part_contexts[dom_id] = PartContext.new(part_name, context_id, locals)
123
+ res = send("#{part_name}_part", *locals)
171
124
  end
172
125
  else
173
126
  new_context do
174
- @_part_contexts[dom_id] = [part_id, part_context_model_id]
175
- res = send("#{part_id}_part")
127
+ @_part_contexts[dom_id] = PartContext.new(part_name, context_id, locals)
128
+ res = send("#{part_name}_part", *locals)
176
129
  end
177
130
  end
178
131
  res
@@ -326,18 +279,6 @@ module Hobo::Dryml
326
279
  end
327
280
 
328
281
 
329
- def part_contexts_js
330
- return "" if part_contexts.empty?
331
-
332
- assigns = part_contexts.map do |dom_id, p|
333
- part_id, model_id = p
334
- "hoboParts.#{dom_id} = ['#{part_id}', '#{model_id}']\n"
335
- end
336
-
337
- "<script>\nvar hoboParts = {}\n" + assigns.join + "</script>\n"
338
- end
339
-
340
-
341
282
  def _tag_locals(attributes, locals)
342
283
  attributes.symbolize_keys!
343
284
  #ensure with and field are not in attributes
@@ -437,7 +378,7 @@ module Hobo::Dryml
437
378
  # single hash
438
379
  def merge_option_procs(general_proc, overriding_proc)
439
380
  if overriding_proc
440
- proc { general_proc.call.merge(overriding_proc.call) }
381
+ proc { merge_attrs(general_proc.call, overriding_proc.call) }
441
382
  else
442
383
  general_proc
443
384
  end
@@ -456,8 +397,24 @@ module Hobo::Dryml
456
397
  end
457
398
 
458
399
 
400
+ def part_contexts_storage_tag
401
+ storage = part_contexts_storage
402
+ storage.blank? ? "" : "<script>\nvar hoboParts = {}\n#{storage}</script>\n"
403
+ end
404
+
405
+
406
+ def part_contexts_storage
407
+ PartContext.client_side_storage(@_part_contexts, session)
408
+ end
409
+
410
+
459
411
  def render_tag(tag_name, attributes)
460
- (send(tag_name, attributes) + part_contexts_js).strip
412
+ (send(tag_name, attributes) + part_contexts_storage_tag).strip
413
+ end
414
+
415
+
416
+ def session
417
+ @view ? @view.session : {}
461
418
  end
462
419
 
463
420
 
@@ -12,16 +12,16 @@ module Hobo
12
12
  def current_user
13
13
  # simple one-hit-per-request cache
14
14
  @current_user or
15
- @current_user = if Hobo.user_model and session and id = session[:user]
16
- Hobo.user_model.find(id)
17
- else
18
- Guest.new
19
- end
15
+ @current_user = if session and id = session[:user]
16
+ Hobo.object_from_dom_id(id)
17
+ else
18
+ Guest.new
19
+ end
20
20
  end
21
21
 
22
22
 
23
23
  def logged_in?
24
- not current_user.guest?
24
+ !(current_user.respond_to?(:guest?) && current_user.guest?)
25
25
  end
26
26
 
27
27
 
@@ -128,17 +128,18 @@ module Hobo
128
128
  end
129
129
 
130
130
 
131
- def type_name(type=nil)
132
- Hobo.type_name(type || this.class)
131
+ def type_id(type=nil)
132
+ type ||= this.is_a?(Class) ? this : this_type
133
+ type == NilClass ? "" : Hobo.type_id(type || this.class)
133
134
  end
134
135
 
135
136
 
136
137
  def type_and_field(*args)
137
138
  if args.empty?
138
- this_parent && this_field && "#{Hobo.type_name(this_parent.class)}_#{this_field}"
139
+ this_parent && this_field && "#{Hobo.type_id(this_parent.class)}_#{this_field}"
139
140
  else
140
141
  type, field = args
141
- "#{type_name(type)}_#{field}"
142
+ "#{Hobo.type_id(type)}_#{field}"
142
143
  end
143
144
  end
144
145
 
@@ -0,0 +1,12 @@
1
+ module Hobo::Migrations
2
+
3
+ class << self
4
+ attr_accessor :ignore_tables
5
+ attr_accessor :ignore_models
6
+ attr_accessor :ignore
7
+ end
8
+ self.ignore_tables = []
9
+ self.ignore_models = []
10
+ self.ignore = []
11
+
12
+ end
@@ -120,7 +120,7 @@ module Hobo
120
120
 
121
121
  def never_show(*fields)
122
122
  @hobo_never_show ||= []
123
- @hobo_never_show.concat(fields.omap{to_sym})
123
+ @hobo_never_show.concat(fields.every(:to_sym))
124
124
  end
125
125
 
126
126
  def never_show?(field)
@@ -142,7 +142,7 @@ module Hobo
142
142
  def set_search_columns(*columns)
143
143
  class_eval %{
144
144
  def self.search_columns
145
- %w{#{columns.omap{to_s} * ' '}}
145
+ %w{#{columns.every(:to_s) * ' '}}
146
146
  end
147
147
  }
148
148
  end
@@ -276,7 +276,7 @@ module Hobo
276
276
  end
277
277
 
278
278
  def search_columns
279
- cols = columns.omap{name}
279
+ cols = columns.every(:name)
280
280
  %w{name title body content}.select{|c| c.in?(cols) }
281
281
  end
282
282
 
@@ -8,7 +8,7 @@ module Hobo
8
8
 
9
9
  VIEWLIB_DIR = "taglibs"
10
10
 
11
- GENERIC_PAGE_TAGS = [:index, :show, :new, :edit, :show_collection, :new_in_collection]
11
+ GENERIC_PAGE_TAGS = [:index, :show, :new, :edit, :show_collection, :new_in_collection, :login, :signup]
12
12
 
13
13
  class << self
14
14
 
@@ -295,7 +295,7 @@ module Hobo
295
295
  attributes = params[model.name.underscore]
296
296
  type_attr = params['type']
297
297
  create_model = if 'type'.in?(model.column_names) and
298
- type_attr and type_attr.in?(model.send(:subclasses).omap{name})
298
+ type_attr and type_attr.in?(model.send(:subclasses).every(:name))
299
299
  type_attr.constantize
300
300
  else
301
301
  model
@@ -556,7 +556,7 @@ module Hobo
556
556
 
557
557
 
558
558
  def with_data_filter(operation, *args, &block)
559
- filter_param = params.keys.ofind {starts_with? "where_"}
559
+ filter_param = params.keys.find &it.starts_with?("where_")
560
560
  proc = filter_param && self.class.data_filter(filter_param[6..-1].to_sym)
561
561
  if proc
562
562
  filter_args = params[filter_param]
@@ -9,8 +9,8 @@ module Hobo::RapidHelper
9
9
  js_options['form'] = options[:form] if options[:form]
10
10
  js_options['params'] = make_params_js(options[:params]) if options[:params]
11
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
12
+ js_options['resetForm'] = options[:reset_form] if options.has_key?(:reset_form)
13
+ js_options['refocusForm'] = options[:refocus_form] if options.has_key?(:refocus_form)
14
14
 
15
15
  js_options.empty? ? nil : options_for_javascript(js_options)
16
16
  end
@@ -26,7 +26,7 @@ module Hobo::RapidHelper
26
26
  def js_result_updates(updates)
27
27
  return '[]' unless updates
28
28
  updates = [updates] unless updates.is_a? Array
29
- pairs = comma_split(updates).omap{split(/\s*=\s*/)}
29
+ pairs = comma_split(updates).map &it.split(/\s*=\s*/)
30
30
  '[' + pairs.map{|p| "{id: #{js_str(p[0])}, result: #{js_str(p[1])}}"}.join(", ") + ']'
31
31
  end
32
32
 
@@ -0,0 +1,80 @@
1
+ module Hobo
2
+
3
+ module UserController
4
+
5
+ @user_models = []
6
+
7
+ class << self
8
+ attr_reader :user_models
9
+
10
+ def included(base)
11
+ base.filter_parameter_logging "password"
12
+ user_models << base.model
13
+ end
14
+ end
15
+
16
+ def login; hobo_login; end
17
+
18
+ def signup; hobo_signup; end
19
+
20
+ def logout; hobo_logout; end
21
+
22
+ def hobo_login(options={})
23
+ options = options.reverse_merge(:success_notice => "You have logged in.",
24
+ :failure_notice => "You did not provide a valid login and password.",
25
+ :redirect_to => {:action => "index"})
26
+
27
+ if request.post?
28
+ user = model.authenticate(params[:login], params[:password])
29
+ if user
30
+ self.current_user = user
31
+ if params[:remember_me] == "1"
32
+ current_user.remember_me
33
+ create_auth_cookie
34
+ end
35
+ redirect_back_or_default(options[:redirect_to])
36
+ flash[:notice] = options[:success_notice]
37
+ else
38
+ flash[:notice] = options[:failure_notice]
39
+ hobo_render
40
+ end
41
+ else
42
+ hobo_render
43
+ end
44
+ end
45
+
46
+
47
+ def hobo_signup(options={})
48
+ options = options.reverse_merge(:notice => "Thanks for signing up!",
49
+ :redirect_to => {:action => "index"})
50
+ if request.post?
51
+ begin
52
+ @user = model.new(params[:user])
53
+ @this = @user
54
+ @user.save!
55
+ self.current_user = @user
56
+ redirect_back_or_default(options[:redirect_to])
57
+ flash[:notice] = options[:notice]
58
+ rescue ActiveRecord::RecordInvalid
59
+ hobo_render
60
+ end
61
+ else
62
+ hobo_render
63
+ end
64
+ end
65
+
66
+
67
+ def hobo_logout(options={})
68
+ options = options.reverse_merge(:notice => "You have been logged out.",
69
+ :redirect_to => {:action => "index"})
70
+
71
+ current_user.forget_me if logged_in?
72
+ cookies.delete :auth_token
73
+ reset_session
74
+ flash[:notice] = options[:notice]
75
+ redirect_back_or_default(options[:redirect_to])
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -35,14 +35,31 @@
35
35
  </def>
36
36
 
37
37
 
38
- <def tag="Table">
39
- <table merge_attrs unless="&this.empty?">
40
- <thead if="&all_parameters[:thead]" param/>
38
+ <def tag="Table" attrs="fields, field_tag">
39
+ <% field_tag ||= "view" %>
40
+ <table merge_attrs="&attributes - attrs_for(:with_fields)" unless="&this.empty?">
41
+ <thead if="&all_parameters[:thead] || fields" param>
42
+ <tr param="field_heading_row">
43
+ <with_field_names merge_attrs="&all_attributes & attrs_for(:with_fields)">
44
+ <th param="#{this.underscore}_heading"><%= this.titleize %></th>
45
+ </with_field_names>
46
+ <th if="&all_parameters[:controls]" class="controls"/>
47
+ </tr>
48
+ </thead>
41
49
  <tbody>
42
50
  <repeat>
43
51
  <tr param if="&can_view?"
44
52
  class="#{scope.even_odd} #{this_type.name.underscore}"
45
53
  hobo_model_id="#{dom_id(this)}">
54
+ <if test="&fields">
55
+ <with_fields merge_attrs="&all_attributes & attrs_for(:with_fields)">
56
+ <td><call_tag tag="&field_tag"/></td>
57
+ </with_fields>
58
+ <td class="controls" param="controls" if="&all_parameters[:controls]">
59
+ <a param="edit_link">Edit</a>
60
+ <delete_button param/>
61
+ </td>
62
+ </if>
46
63
  </tr>
47
64
  </repeat>
48
65
  </tbody>
@@ -68,7 +85,7 @@
68
85
 
69
86
  <def tag="card">
70
87
  <%= poly = call_polymorphic_tag('card', attributes) %>
71
- <div class="card" unless="&poly"><human_type/>: <a/></div>
88
+ <div class="card" unless="&poly"><type_name/>: <a/></div>
72
89
  </def>
73
90
 
74
91
 
@@ -120,6 +137,19 @@
120
137
  end
121
138
  %></def>
122
139
 
140
+ <def tag="type_name" attrs="type, plural, lowercase"><%=
141
+ type ||= if this.is_a?(Class)
142
+ this
143
+ elsif this.respond_to? :proxy_reflection
144
+ this.proxy_reflection.klass
145
+ else
146
+ this.class
147
+ end
148
+ name = type.name.titleize
149
+ name = name.pluralize if plural
150
+ name = name.downcase if lowercase
151
+ name
152
+ %></def>
123
153
 
124
154
  <def tag="a" attrs="action, to, params, resource_type, href"><%=
125
155
  content = tagbody.call if tagbody
@@ -174,7 +204,7 @@
174
204
  has_many_view(attributes)
175
205
  end
176
206
  else
177
- attrs = add_classes(attributes, "view", type_name, type_and_field)
207
+ attrs = add_classes(attributes, "view", type_id, type_and_field)
178
208
  attrs[:hobo_model_id] = this_field_dom_id if this_parent && this_parent.respond_to?(:typed_id)
179
209
 
180
210
  view_tag = find_polymorphic_tag("view")
@@ -210,7 +240,7 @@
210
240
 
211
241
  <def tag="view" for="Date"><%= this.to_s(:long) %></def>
212
242
 
213
- <def tag="view" for="Time"><%= this.to_s(:long) %></def>
243
+ <def tag="view" for="Time" attrs="format"><%= format ? this.strftime(format) : this.to_s(:long) %></def>
214
244
 
215
245
  <def tag="view" for="Numeric" attrs="format"><%= format ? format % this : this.to_s %></def>
216
246
 
@@ -228,20 +258,6 @@
228
258
 
229
259
  <def tag="view" for="TrueClass"><%= this ? 'Yes' : 'No' %></def>
230
260
 
231
- <def tag="human_type" attrs="style"><%=
232
- if can_view?
233
- res = if this.respond_to? :proxy_reflection
234
- this.proxy_reflection.klass.name.pluralize
235
- elsif this.is_a? Class
236
- this.name
237
- else
238
- this.class.name
239
- end
240
- res.underscore.humanize.send(style || :titleize)
241
- end
242
- %></def>
243
-
244
-
245
261
  <def tag="count" attrs="label, prefix, unless_none"><%=
246
262
  raise Exception.new("asked for count of a string") if this.is_a?(String)
247
263