actionpack 1.12.5 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (179) hide show
  1. data/CHANGELOG +517 -15
  2. data/MIT-LICENSE +1 -1
  3. data/README +18 -20
  4. data/Rakefile +7 -4
  5. data/examples/address_book_controller.rb +3 -3
  6. data/examples/blog_controller.cgi +3 -3
  7. data/examples/debate_controller.cgi +5 -5
  8. data/lib/action_controller.rb +2 -2
  9. data/lib/action_controller/assertions.rb +73 -311
  10. data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
  11. data/lib/action_controller/assertions/dom_assertions.rb +25 -0
  12. data/lib/action_controller/assertions/model_assertions.rb +12 -0
  13. data/lib/action_controller/assertions/response_assertions.rb +140 -0
  14. data/lib/action_controller/assertions/routing_assertions.rb +82 -0
  15. data/lib/action_controller/assertions/selector_assertions.rb +571 -0
  16. data/lib/action_controller/assertions/tag_assertions.rb +117 -0
  17. data/lib/action_controller/base.rb +334 -163
  18. data/lib/action_controller/benchmarking.rb +3 -6
  19. data/lib/action_controller/caching.rb +83 -22
  20. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
  21. data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
  22. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
  23. data/lib/action_controller/cgi_process.rb +50 -27
  24. data/lib/action_controller/components.rb +21 -25
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
  27. data/lib/action_controller/filters.rb +448 -225
  28. data/lib/action_controller/flash.rb +24 -20
  29. data/lib/action_controller/helpers.rb +2 -5
  30. data/lib/action_controller/integration.rb +40 -16
  31. data/lib/action_controller/layout.rb +11 -8
  32. data/lib/action_controller/macros/auto_complete.rb +3 -2
  33. data/lib/action_controller/macros/in_place_editing.rb +3 -2
  34. data/lib/action_controller/mime_responds.rb +41 -29
  35. data/lib/action_controller/mime_type.rb +68 -10
  36. data/lib/action_controller/pagination.rb +4 -3
  37. data/lib/action_controller/request.rb +22 -14
  38. data/lib/action_controller/rescue.rb +25 -22
  39. data/lib/action_controller/resources.rb +302 -0
  40. data/lib/action_controller/response.rb +20 -2
  41. data/lib/action_controller/response.rb.rej +17 -0
  42. data/lib/action_controller/routing.rb +1165 -567
  43. data/lib/action_controller/scaffolding.rb +30 -31
  44. data/lib/action_controller/session/active_record_store.rb +2 -0
  45. data/lib/action_controller/session/drb_store.rb +4 -0
  46. data/lib/action_controller/session/mem_cache_store.rb +4 -0
  47. data/lib/action_controller/session_management.rb +6 -9
  48. data/lib/action_controller/status_codes.rb +89 -0
  49. data/lib/action_controller/streaming.rb +6 -15
  50. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
  51. data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
  52. data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
  53. data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
  54. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  55. data/lib/action_controller/test_process.rb +52 -30
  56. data/lib/action_controller/url_rewriter.rb +63 -29
  57. data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
  58. data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
  59. data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
  60. data/lib/action_controller/verification.rb +22 -11
  61. data/lib/action_pack.rb +1 -1
  62. data/lib/action_pack/version.rb +2 -2
  63. data/lib/action_view.rb +1 -1
  64. data/lib/action_view/base.rb +46 -43
  65. data/lib/action_view/compiled_templates.rb +1 -1
  66. data/lib/action_view/helpers/active_record_helper.rb +54 -17
  67. data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
  68. data/lib/action_view/helpers/capture_helper.rb +1 -1
  69. data/lib/action_view/helpers/date_helper.rb +258 -136
  70. data/lib/action_view/helpers/debug_helper.rb +1 -1
  71. data/lib/action_view/helpers/deprecated_helper.rb +34 -0
  72. data/lib/action_view/helpers/form_helper.rb +75 -35
  73. data/lib/action_view/helpers/form_options_helper.rb +7 -5
  74. data/lib/action_view/helpers/form_tag_helper.rb +44 -6
  75. data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
  76. data/lib/action_view/helpers/javascript_helper.rb +71 -10
  77. data/lib/action_view/helpers/javascripts/controls.js +41 -23
  78. data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
  79. data/lib/action_view/helpers/javascripts/effects.js +293 -163
  80. data/lib/action_view/helpers/javascripts/prototype.js +897 -389
  81. data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
  82. data/lib/action_view/helpers/number_helper.rb +111 -65
  83. data/lib/action_view/helpers/prototype_helper.rb +84 -109
  84. data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
  85. data/lib/action_view/helpers/tag_helper.rb +69 -16
  86. data/lib/action_view/helpers/text_helper.rb +149 -112
  87. data/lib/action_view/helpers/url_helper.rb +200 -107
  88. data/lib/action_view/template_error.rb +66 -42
  89. data/test/abstract_unit.rb +4 -2
  90. data/test/active_record_unit.rb +84 -56
  91. data/test/activerecord/active_record_assertions_test.rb +26 -18
  92. data/test/activerecord/active_record_store_test.rb +4 -36
  93. data/test/activerecord/pagination_test.rb +1 -6
  94. data/test/controller/action_pack_assertions_test.rb +230 -113
  95. data/test/controller/addresses_render_test.rb +2 -6
  96. data/test/controller/assert_select_test.rb +576 -0
  97. data/test/controller/base_test.rb +73 -3
  98. data/test/controller/caching_test.rb +228 -0
  99. data/test/controller/capture_test.rb +12 -10
  100. data/test/controller/cgi_test.rb +89 -12
  101. data/test/controller/components_test.rb +24 -2
  102. data/test/controller/content_type_test.rb +139 -0
  103. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  104. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  105. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  106. data/test/controller/cookie_test.rb +33 -25
  107. data/test/controller/deprecated_instance_variables_test.rb +48 -0
  108. data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
  109. data/test/controller/fake_controllers.rb +0 -1
  110. data/test/controller/filters_test.rb +301 -16
  111. data/test/controller/flash_test.rb +19 -2
  112. data/test/controller/helper_test.rb +2 -2
  113. data/test/controller/integration_test.rb +154 -0
  114. data/test/controller/layout_test.rb +115 -1
  115. data/test/controller/mime_responds_test.rb +94 -0
  116. data/test/controller/mime_type_test.rb +9 -0
  117. data/test/controller/new_render_test.rb +161 -11
  118. data/test/controller/raw_post_test.rb +52 -15
  119. data/test/controller/redirect_test.rb +27 -14
  120. data/test/controller/render_test.rb +76 -29
  121. data/test/controller/request_test.rb +55 -4
  122. data/test/controller/resources_test.rb +274 -0
  123. data/test/controller/routing_test.rb +1533 -824
  124. data/test/controller/selector_test.rb +628 -0
  125. data/test/controller/send_file_test.rb +9 -1
  126. data/test/controller/session_management_test.rb +51 -0
  127. data/test/controller/test_test.rb +113 -29
  128. data/test/controller/url_rewriter_test.rb +86 -17
  129. data/test/controller/verification_test.rb +19 -17
  130. data/test/controller/webservice_test.rb +0 -7
  131. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  132. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  133. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  134. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  135. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
  136. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
  137. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
  138. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
  139. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
  140. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
  141. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
  142. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
  143. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
  144. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
  145. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
  146. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
  147. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
  148. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
  149. data/test/fixtures/multipart/binary_file +0 -0
  150. data/test/fixtures/public/javascripts/application.js +1 -0
  151. data/test/fixtures/test/_hello.rxml +1 -0
  152. data/test/fixtures/test/hello_world_container.rxml +3 -0
  153. data/test/fixtures/topic.rb +2 -2
  154. data/test/template/active_record_helper_test.rb +83 -12
  155. data/test/template/asset_tag_helper_test.rb +75 -95
  156. data/test/template/compiled_templates_test.rb +1 -0
  157. data/test/template/date_helper_test.rb +873 -181
  158. data/test/template/deprecated_helper_test.rb +36 -0
  159. data/test/template/deprecated_instance_variables_test.rb +43 -0
  160. data/test/template/form_helper_test.rb +77 -1
  161. data/test/template/form_options_helper_test.rb +4 -0
  162. data/test/template/form_tag_helper_test.rb +66 -2
  163. data/test/template/java_script_macros_helper_test.rb +4 -1
  164. data/test/template/javascript_helper_test.rb +29 -0
  165. data/test/template/number_helper_test.rb +63 -27
  166. data/test/template/prototype_helper_test.rb +77 -34
  167. data/test/template/tag_helper_test.rb +34 -6
  168. data/test/template/text_helper_test.rb +69 -34
  169. data/test/template/url_helper_test.rb +168 -16
  170. data/test/testing_sandbox.rb +7 -22
  171. metadata +66 -20
  172. data/filler.txt +0 -50
  173. data/lib/action_controller/code_generation.rb +0 -235
  174. data/lib/action_controller/vendor/xml_simple.rb +0 -1019
  175. data/test/controller/caching_filestore.rb +0 -74
  176. data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
  177. data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
  178. data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
  179. data/test/fixtures/dont_load.rb +0 -3
@@ -1,7 +1,6 @@
1
1
  module ActionController #:nodoc:
2
2
  module Verification #:nodoc:
3
- def self.append_features(base) #:nodoc:
4
- super
3
+ def self.included(base) #:nodoc:
5
4
  base.extend(ClassMethods)
6
5
  end
7
6
 
@@ -18,19 +17,26 @@ module ActionController #:nodoc:
18
17
  # Usage:
19
18
  #
20
19
  # class GlobalController < ActionController::Base
21
- # # prevent the #update_settings action from being invoked unless
22
- # # the 'admin_privileges' request parameter exists.
20
+ # # Prevent the #update_settings action from being invoked unless
21
+ # # the 'admin_privileges' request parameter exists. The
22
+ # # settings action will be redirected to in current controller
23
+ # # if verification fails.
23
24
  # verify :params => "admin_privileges", :only => :update_post,
24
25
  # :redirect_to => { :action => "settings" }
25
26
  #
26
- # # disallow a post from being updated if there was no information
27
+ # # Disallow a post from being updated if there was no information
27
28
  # # submitted with the post, and if there is no active post in the
28
- # # session, and if there is no "note" key in the flash.
29
+ # # session, and if there is no "note" key in the flash. The route
30
+ # # named category_url will be redirected to if verification fails.
31
+ #
29
32
  # verify :params => "post", :session => "post", "flash" => "note",
30
33
  # :only => :update_post,
31
34
  # :add_flash => { "alert" => "Failed to create your message" },
32
35
  # :redirect_to => :category_url
33
36
  #
37
+ # Note that these prerequisites are not business rules. They do not examine
38
+ # the content of the session or the parameters. That level of validation should
39
+ # be encapsulated by your domain model or helper methods in the controller.
34
40
  module ClassMethods
35
41
  # Verify the given actions so that if certain prerequisites are not met,
36
42
  # the user is redirected to a different action. The +options+ parameter
@@ -40,7 +46,7 @@ module ActionController #:nodoc:
40
46
  # be in the <tt>params</tt> hash in order for the action(s) to be safely
41
47
  # called.
42
48
  # * <tt>:session</tt>: a single key or an array of keys that must
43
- # be in the @session in order for the action(s) to be safely called.
49
+ # be in the <tt>session</tt> in order for the action(s) to be safely called.
44
50
  # * <tt>:flash</tt>: a single key or an array of keys that must
45
51
  # be in the flash in order for the action(s) to be safely called.
46
52
  # * <tt>:method</tt>: a single key or an array of keys--any one of which
@@ -51,8 +57,12 @@ module ActionController #:nodoc:
51
57
  # from an Ajax call or not.
52
58
  # * <tt>:add_flash</tt>: a hash of name/value pairs that should be merged
53
59
  # into the session's flash if the prerequisites cannot be satisfied.
60
+ # * <tt>:add_headers</tt>: a hash of name/value pairs that should be
61
+ # merged into the response's headers hash if the prerequisites cannot
62
+ # be satisfied.
54
63
  # * <tt>:redirect_to</tt>: the redirection parameters to be used when
55
- # redirecting if the prerequisites cannot be satisfied.
64
+ # redirecting if the prerequisites cannot be satisfied. You can
65
+ # redirect either to named route or to the action in some controller.
56
66
  # * <tt>:render</tt>: the render parameters to be used when
57
67
  # the prerequisites cannot be satisfied.
58
68
  # * <tt>:only</tt>: only apply this verification to the actions specified
@@ -69,19 +79,20 @@ module ActionController #:nodoc:
69
79
 
70
80
  def verify_action(options) #:nodoc:
71
81
  prereqs_invalid =
72
- [*options[:params] ].find { |v| @params[v].nil? } ||
73
- [*options[:session]].find { |v| @session[v].nil? } ||
82
+ [*options[:params] ].find { |v| params[v].nil? } ||
83
+ [*options[:session]].find { |v| session[v].nil? } ||
74
84
  [*options[:flash] ].find { |v| flash[v].nil? }
75
85
 
76
86
  if !prereqs_invalid && options[:method]
77
87
  prereqs_invalid ||=
78
- [*options[:method]].all? { |v| @request.method != v.to_sym }
88
+ [*options[:method]].all? { |v| request.method != v.to_sym }
79
89
  end
80
90
 
81
91
  prereqs_invalid ||= (request.xhr? != options[:xhr]) unless options[:xhr].nil?
82
92
 
83
93
  if prereqs_invalid
84
94
  flash.update(options[:add_flash]) if options[:add_flash]
95
+ response.headers.update(options[:add_headers]) if options[:add_headers]
85
96
  unless performed?
86
97
  render(options[:render]) if options[:render]
87
98
  redirect_to(options[:redirect_to]) if options[:redirect_to]
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2006 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -1,8 +1,8 @@
1
1
  module ActionPack #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 12
5
- TINY = 5
4
+ MINOR = 13
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2006 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -1,7 +1,6 @@
1
1
  require 'erb'
2
2
 
3
3
  module ActionView #:nodoc:
4
-
5
4
  class ActionViewError < StandardError #:nodoc:
6
5
  end
7
6
 
@@ -54,13 +53,22 @@ module ActionView #:nodoc:
54
53
  #
55
54
  # You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values:
56
55
  #
57
- # <%= render "shared/header", { "headline" => "Welcome", "person" => person } %>
56
+ # <%= render "shared/header", { :headline => "Welcome", :person => person } %>
58
57
  #
59
58
  # These can now be accessed in shared/header with:
60
59
  #
61
60
  # Headline: <%= headline %>
62
61
  # First name: <%= person.first_name %>
63
62
  #
63
+ # If you need to find out whether a certain local variable has been assigned a value in a particular render call,
64
+ # you need to use the following pattern:
65
+ #
66
+ # <% if local_assigns.has_key? :headline %>
67
+ # Headline: <%= headline %>
68
+ # <% end %>
69
+ #
70
+ # Testing using <tt>defined? headline</tt> will not work. This is an implementation restriction.
71
+ #
64
72
  # == Template caching
65
73
  #
66
74
  # By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will
@@ -148,7 +156,8 @@ module ActionView #:nodoc:
148
156
  attr_accessor :base_path, :assigns, :template_extension
149
157
  attr_accessor :controller
150
158
 
151
- attr_reader :logger, :params, :request, :response, :session, :headers, :flash
159
+ attr_reader :logger, :response, :headers
160
+ attr_internal *ActionController::Base::DEPRECATED_INSTANCE_VARIABLES
152
161
 
153
162
  # Specify trim mode for the ERB compiler. Defaults to '-'.
154
163
  # See ERB documentation for suitable values.
@@ -199,7 +208,7 @@ module ActionView #:nodoc:
199
208
  end
200
209
 
201
210
  def self.load_helpers(helper_dir)#:nodoc:
202
- Dir.foreach(helper_dir) do |helper_file|
211
+ Dir.entries(helper_dir).sort.each do |helper_file|
203
212
  next unless helper_file =~ /^([a-z][a-z_]*_helper).rb$/
204
213
  require File.join(helper_dir, $1)
205
214
  helper_module_name = $1.camelize
@@ -301,6 +310,9 @@ module ActionView #:nodoc:
301
310
  # will only be read if it has to be compiled.
302
311
  #
303
312
  def compile_and_render_template(extension, template = nil, file_path = nil, local_assigns = {}) #:nodoc:
313
+ # convert string keys to symbols if requested
314
+ local_assigns = local_assigns.symbolize_keys if @@local_assigns_support_string_keys
315
+
304
316
  # compile the given template, if necessary
305
317
  if compile_template?(template, file_path, local_assigns)
306
318
  template ||= read_template_file(file_path, extension)
@@ -309,9 +321,7 @@ module ActionView #:nodoc:
309
321
 
310
322
  # Get the method name for this template and run it
311
323
  method_name = @@method_names[file_path || template]
312
- evaluate_assigns
313
-
314
- local_assigns = local_assigns.symbolize_keys if @@local_assigns_support_string_keys
324
+ evaluate_assigns
315
325
 
316
326
  send(method_name, local_assigns) do |*name|
317
327
  instance_variable_get "@content_for_#{name.first || 'layout'}"
@@ -337,14 +347,14 @@ module ActionView #:nodoc:
337
347
  def builder_template_exists?(template_path)#:nodoc:
338
348
  template_exists?(template_path, :rxml)
339
349
  end
340
-
350
+
341
351
  def javascript_template_exists?(template_path)#:nodoc:
342
352
  template_exists?(template_path, :rjs)
343
353
  end
344
354
 
345
355
  def file_exists?(template_path)#:nodoc:
346
356
  template_file_name, template_file_extension = path_and_extension(template_path)
347
-
357
+
348
358
  if template_file_extension
349
359
  template_exists?(template_file_name, template_file_extension)
350
360
  else
@@ -374,11 +384,11 @@ module ActionView #:nodoc:
374
384
  template_path_without_extension = template_path.sub(/\.(\w+)$/, '')
375
385
  [ template_path_without_extension, $1 ]
376
386
  end
377
-
387
+
378
388
  def cached_template_extension(template_path)
379
389
  @@cache_template_extensions && @@cached_template_extension[template_path]
380
- end
381
-
390
+ end
391
+
382
392
  def find_template_extension_for(template_path)
383
393
  if match = delegate_template_exists?(template_path)
384
394
  match.first.to_sym
@@ -386,7 +396,7 @@ module ActionView #:nodoc:
386
396
  elsif builder_template_exists?(template_path): :rxml
387
397
  elsif javascript_template_exists?(template_path): :rjs
388
398
  else
389
- raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path}"
399
+ raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path} in #{@base_path}"
390
400
  end
391
401
  end
392
402
 
@@ -416,7 +426,7 @@ module ActionView #:nodoc:
416
426
  local_assigns.empty? ||
417
427
  ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) })
418
428
  end
419
-
429
+
420
430
  # Check whether compilation is necessary.
421
431
  # Compile if the inline template or file has not been compiled yet.
422
432
  # Or if local_assigns has a new key, which isn't supported by the compiled code yet.
@@ -427,8 +437,8 @@ module ActionView #:nodoc:
427
437
 
428
438
  if @@compile_time[render_symbol] && supports_local_assigns?(render_symbol, local_assigns)
429
439
  if file_name && !@@cache_template_loading
430
- @@compile_time[render_symbol] < File.mtime(file_name) || (File.symlink?(file_name) ?
431
- @@compile_time[render_symbol] < File.lstat(file_name).mtime : false)
440
+ @@compile_time[render_symbol] < File.mtime(file_name) ||
441
+ (File.symlink?(file_name) && (@@compile_time[render_symbol] < File.lstat(file_name).mtime))
432
442
  end
433
443
  else
434
444
  true
@@ -440,11 +450,11 @@ module ActionView #:nodoc:
440
450
  if template_requires_setup?(extension)
441
451
  body = case extension.to_sym
442
452
  when :rxml
453
+ "controller.response.content_type ||= 'application/xml'\n" +
443
454
  "xml = Builder::XmlMarkup.new(:indent => 2)\n" +
444
- "@controller.headers['Content-Type'] ||= 'application/xml'\n" +
445
455
  template
446
456
  when :rjs
447
- "@controller.headers['Content-Type'] ||= 'text/javascript'\n" +
457
+ "controller.response.content_type ||= 'text/javascript'\n" +
448
458
  "update_page do |page|\n#{template}\nend"
449
459
  end
450
460
  else
@@ -457,7 +467,7 @@ module ActionView #:nodoc:
457
467
 
458
468
  locals_code = ""
459
469
  locals_keys.each do |key|
460
- locals_code << "#{key} = local_assigns[:#{key}] if local_assigns.has_key?(:#{key})\n"
470
+ locals_code << "#{key} = local_assigns[:#{key}]\n"
461
471
  end
462
472
 
463
473
  "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
@@ -472,34 +482,27 @@ module ActionView #:nodoc:
472
482
  end
473
483
 
474
484
  def assign_method_name(extension, template, file_name)
475
- method_name = '_run_'
476
- method_name << "#{extension}_" if extension
477
-
478
- if file_name
479
- file_path = File.expand_path(file_name)
480
- base_path = File.expand_path(@base_path)
481
-
482
- i = file_path.index(base_path)
483
- l = base_path.length
485
+ method_key = file_name || template
486
+ @@method_names[method_key] ||= compiled_method_name(extension, template, file_name)
487
+ end
484
488
 
485
- method_name_file_part = i ? file_path[i+l+1,file_path.length-l-1] : file_path.clone
486
- method_name_file_part.sub!(/\.r(html|xml|js)$/,'')
487
- method_name_file_part.tr!('/:-', '_')
488
- method_name_file_part.gsub!(/[^a-zA-Z0-9_]/){|s| s[0].to_s}
489
+ def compiled_method_name(extension, template, file_name)
490
+ ['_run', extension, compiled_method_name_file_path_segment(file_name)].compact.join('_').to_sym
491
+ end
489
492
 
490
- method_name += method_name_file_part
493
+ def compiled_method_name_file_path_segment(file_name)
494
+ if file_name
495
+ s = File.expand_path(file_name)
496
+ s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
497
+ s.gsub!(/([^a-zA-Z0-9_])/) { $1[0].to_s }
498
+ s
491
499
  else
492
- @@inline_template_count += 1
493
- method_name << @@inline_template_count.to_s
500
+ (@@inline_template_count += 1).to_s
494
501
  end
495
-
496
- @@method_names[file_name || template] = method_name.intern
497
502
  end
498
503
 
499
504
  def compile_template(extension, template, file_name, local_assigns)
500
- method_key = file_name || template
501
-
502
- render_symbol = @@method_names[method_key] || assign_method_name(extension, template, file_name)
505
+ render_symbol = assign_method_name(extension, template, file_name)
503
506
  render_source = create_template_source(extension, template, render_symbol, local_assigns.keys)
504
507
 
505
508
  line_offset = @@template_args[render_symbol].size
@@ -516,18 +519,18 @@ module ActionView #:nodoc:
516
519
  else
517
520
  CompiledTemplates.module_eval(render_source, 'compiled-template', -line_offset)
518
521
  end
519
- rescue Object => e
522
+ rescue Exception => e # errors from template code
520
523
  if logger
521
524
  logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}"
522
525
  logger.debug "Function body: #{render_source}"
523
526
  logger.debug "Backtrace: #{e.backtrace.join("\n")}"
524
527
  end
525
528
 
526
- raise TemplateError.new(@base_path, method_key, @assigns, template, e)
529
+ raise TemplateError.new(@base_path, file_name || template, @assigns, template, e)
527
530
  end
528
531
 
529
532
  @@compile_time[render_symbol] = Time.now
530
- # logger.debug "Compiled template #{method_key}\n ==> #{render_symbol}" if logger
533
+ # logger.debug "Compiled template #{file_name || template}\n ==> #{render_symbol}" if logger
531
534
  end
532
535
  end
533
536
  end
@@ -55,7 +55,7 @@ module ActionView
55
55
  begin
56
56
  module_eval(method_def, fake_file_name, initial_line_number)
57
57
  @mtimes[full_key(identifier, arg_names)] = Time.now
58
- rescue Object => e
58
+ rescue Exception => e # errors from compiled source
59
59
  e.blame_file! identifier
60
60
  raise
61
61
  end
@@ -85,36 +85,62 @@ module ActionView
85
85
  # <%= error_message_on "post", "title", "Title simply ", " (or it won't work)", "inputError" %> =>
86
86
  # <div class="inputError">Title simply can't be empty (or it won't work)</div>
87
87
  def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError")
88
- if errors = instance_variable_get("@#{object}").errors.on(method)
88
+ if (obj = instance_variable_get("@#{object}")) && (errors = obj.errors.on(method))
89
89
  content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class)
90
+ else
91
+ ''
90
92
  end
91
93
  end
92
94
 
93
- # Returns a string with a div containing all the error messages for the object located as an instance variable by the name
94
- # of <tt>object_name</tt>. This div can be tailored by the following options:
95
+ # Returns a string with a div containing all of the error messages for the objects located as instance variables by the names
96
+ # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are
97
+ # provided.
98
+ #
99
+ # This div can be tailored by the following options:
95
100
  #
96
101
  # * <tt>header_tag</tt> - Used for the header of the error div (default: h2)
97
102
  # * <tt>id</tt> - The id of the error div (default: errorExplanation)
98
103
  # * <tt>class</tt> - The class of the error div (default: errorExplanation)
104
+ # * <tt>object_name</tt> - The object name to use in the header, or
105
+ # any text that you prefer. If <tt>object_name</tt> is not set, the name of
106
+ # the first object will be used.
107
+ #
108
+ # Specifying one object:
109
+ #
110
+ # error_messages_for 'user'
111
+ #
112
+ # Specifying more than one object (and using the name 'user' in the
113
+ # header as the <tt>object_name</tt> instead of 'user_common'):
114
+ #
115
+ # error_messages_for 'user_common', 'user', :object_name => 'user'
99
116
  #
100
117
  # NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what
101
118
  # you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors
102
119
  # instance yourself and set it up. View the source of this method to see how easy it is.
103
- def error_messages_for(object_name, options = {})
104
- options = options.symbolize_keys
105
- object = instance_variable_get("@#{object_name}")
106
- if object && !object.errors.empty?
107
- content_tag("div",
108
- content_tag(
109
- options[:header_tag] || "h2",
110
- "#{pluralize(object.errors.count, "error")} prohibited this #{object_name.to_s.gsub("_", " ")} from being saved"
111
- ) +
112
- content_tag("p", "There were problems with the following fields:") +
113
- content_tag("ul", object.errors.full_messages.collect { |msg| content_tag("li", msg) }),
114
- "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
120
+ def error_messages_for(*params)
121
+ options = params.last.is_a?(Hash) ? params.pop.symbolize_keys : {}
122
+ objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
123
+ count = objects.inject(0) {|sum, object| sum + object.errors.count }
124
+ unless count.zero?
125
+ html = {}
126
+ [:id, :class].each do |key|
127
+ if options.include?(key)
128
+ value = options[key]
129
+ html[key] = value unless value.blank?
130
+ else
131
+ html[key] = 'errorExplanation'
132
+ end
133
+ end
134
+ header_message = "#{pluralize(count, 'error')} prohibited this #{(options[:object_name] || params.first).to_s.gsub('_', ' ')} from being saved"
135
+ error_messages = objects.map {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }
136
+ content_tag(:div,
137
+ content_tag(options[:header_tag] || :h2, header_message) <<
138
+ content_tag(:p, 'There were problems with the following fields:') <<
139
+ content_tag(:ul, error_messages),
140
+ html
115
141
  )
116
142
  else
117
- ""
143
+ ''
118
144
  end
119
145
  end
120
146
 
@@ -137,12 +163,14 @@ module ActionView
137
163
  to_input_field_tag(field_type, options)
138
164
  when :text
139
165
  to_text_area_tag(options)
140
- when :integer, :float
166
+ when :integer, :float, :decimal
141
167
  to_input_field_tag("text", options)
142
168
  when :date
143
169
  to_date_select_tag(options)
144
170
  when :datetime, :timestamp
145
171
  to_datetime_select_tag(options)
172
+ when :time
173
+ to_time_select_tag(options)
146
174
  when :boolean
147
175
  to_boolean_select_tag(options)
148
176
  end
@@ -184,6 +212,15 @@ module ActionView
184
212
  end
185
213
  end
186
214
 
215
+ alias_method :to_time_select_tag_without_error_wrapping, :to_time_select_tag
216
+ def to_time_select_tag(options = {})
217
+ if object.respond_to?("errors") && object.errors.respond_to?("on")
218
+ error_wrapping(to_time_select_tag_without_error_wrapping(options), object.errors.on(@method_name))
219
+ else
220
+ to_time_select_tag_without_error_wrapping(options)
221
+ end
222
+ end
223
+
187
224
  def error_wrapping(html_tag, has_error)
188
225
  has_error ? Base.field_error_proc.call(html_tag, self) : html_tag
189
226
  end