hobo 0.6 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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