actionpack 1.11.0 → 1.11.1

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 (40) hide show
  1. data/CHANGELOG +45 -0
  2. data/lib/action_controller/assertions.rb +1 -1
  3. data/lib/action_controller/base.rb +24 -12
  4. data/lib/action_controller/caching.rb +1 -0
  5. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +1 -0
  6. data/lib/action_controller/cgi_process.rb +44 -27
  7. data/lib/action_controller/components.rb +2 -2
  8. data/lib/action_controller/flash.rb +16 -7
  9. data/lib/action_controller/helpers.rb +12 -1
  10. data/lib/action_controller/layout.rb +3 -1
  11. data/lib/action_controller/macros/in_place_editing.rb +1 -1
  12. data/lib/action_controller/request.rb +20 -16
  13. data/lib/action_controller/session/active_record_store.rb +57 -51
  14. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -2
  15. data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -1
  16. data/lib/action_controller/vendor/html-scanner/html/node.rb.rej +17 -0
  17. data/lib/action_pack/version.rb +2 -2
  18. data/lib/action_view/base.rb +4 -5
  19. data/lib/action_view/helpers/asset_tag_helper.rb +2 -2
  20. data/lib/action_view/helpers/form_options_helper.rb +1 -1
  21. data/lib/action_view/helpers/form_tag_helper.rb +1 -1
  22. data/lib/action_view/helpers/java_script_macros_helper.rb +11 -9
  23. data/lib/action_view/helpers/javascripts/controls.js +30 -1
  24. data/lib/action_view/helpers/javascripts/dragdrop.js +37 -17
  25. data/lib/action_view/helpers/javascripts/effects.js +3 -91
  26. data/lib/action_view/helpers/javascripts/prototype.js +109 -67
  27. data/lib/action_view/helpers/text_helper.rb +30 -9
  28. data/rakefile +2 -2
  29. data/test/controller/active_record_assertions_test.rb +1 -0
  30. data/test/controller/active_record_store_test.rb +12 -6
  31. data/test/controller/flash_test.rb +1 -1
  32. data/test/controller/helper_test.rb +21 -5
  33. data/test/controller/new_render_test.rb +31 -0
  34. data/test/controller/request_test.rb +5 -0
  35. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  36. data/test/fixtures/test/render_file_with_ivar.rhtml +1 -0
  37. data/test/fixtures/test/render_file_with_locals.rhtml +1 -0
  38. data/test/template/form_options_helper_test.rb +16 -6
  39. data/test/template/text_helper_test.rb +7 -0
  40. metadata +7 -3
data/CHANGELOG CHANGED
@@ -1,3 +1,48 @@
1
+ *1.11.1* (December 7th, 2005)
2
+
3
+ * More robust relative url root discovery for SCGI compatibility. This solves the 'SCGI routes problem' -- you no longer need to prefix all your routes with the name of the SCGI mountpoint. #3070 [Dave Ringoen]
4
+
5
+ * Fix docs for text_area_tag. #3083. [Christopher Cotton]
6
+
7
+ * Make ActionController's render honor the :locals option when rendering a :file. #1665. [Emanuel Borsboom, Marcel Molina Jr.]
8
+
9
+ * Don't put flash in session if sessions are disabled. [Jeremy Kemper]
10
+
11
+ * Strip out trailing &_= for raw post bodies. Closes #2868. [Sam Stephenson]
12
+
13
+ * Correct docs for automatic layout assignment. #2610. [Charles M. Gerungan]
14
+
15
+ * Always create new AR sessions rather than trying too hard to avoid database traffic. #2731 [Jeremy Kemper]
16
+
17
+ * Update to Prototype 1.4.0_rc4. Closes #2943 (old Array.prototype.reverse behavior can be obtained by passing false as an argument). [Sam Stephenson]
18
+
19
+ * Update to Prototype 1.4.0_rc3. Closes #1893, #2505, #2550, #2748, #2783. [Sam Stephenson]
20
+
21
+ * Updated docs for in_place_editor, fixes a couple bugs and offers extended support for external controls [Justin Palmer]
22
+
23
+ * Rename Version constant to VERSION. #2802 [Marcel Molina Jr.]
24
+
25
+ * Remove the unused, slow response_dump and session_dump variables from error pages. #1222 [lmarlow@yahoo.com]
26
+
27
+ * Update to latest script.aculo.us version (as of [3031])
28
+
29
+ * Update documentation for render :file. #2858 [Tom Werner]
30
+
31
+ * Only include builtin filters whose filenames match /^[a-z][a-z_]*_helper.rb$/ to avoid including operating system metadata such as ._foo_helper.rb. #2855 [court3nay@gmail.com]
32
+
33
+ * options_for_select allows any objects which respond_to? :first and :last rather than restricting to Array and Range. #2824 [Jacob Robbins <jrobbins@cmj.com>, Jeremy Kemper]
34
+
35
+ * The auto_link text helper accepts an optional block to format the link text for each url and email address. Example: auto_link(post.body) { |text| truncate(text, 10) } [Jeremy Kemper]
36
+
37
+ * assert_tag uses exact matches for string conditions, instead of partial matches. Use regex to do partial matches. #2799 [Jamis Buck]
38
+
39
+ * CGI::Session::ActiveRecordStore.data_column_name = 'foobar' to use a different session data column than the 'data' default. [nbpwie102@sneakemail.com]
40
+
41
+ * Do not raise an exception when default helper is missing; log a debug message instead. It's nice to delete empty helpers. [Jeremy Kemper]
42
+
43
+ * Controllers with acronyms in their names (e.g. PDFController) require the correct default helper (PDFHelper in file pdf_helper.rb). #2262 [jeff@opendbms.com]
44
+
45
+
1
46
  *1.11.0* (November 7th, 2005)
2
47
 
3
48
  * Added request as instance method to views, so you can do <%= request.env["HTTP_REFERER"] %>, just like you can already access response, session, and the likes [DHH]
@@ -1,7 +1,7 @@
1
1
  require 'test/unit'
2
2
  require 'test/unit/assertions'
3
3
  require 'rexml/document'
4
- require "#{File.dirname(__FILE__)}/vendor/html-scanner/html/document"
4
+ require File.dirname(__FILE__) + "/vendor/html-scanner/html/document"
5
5
 
6
6
  module Test #:nodoc:
7
7
  module Unit #:nodoc:
@@ -28,11 +28,15 @@ module ActionController #:nodoc:
28
28
  end
29
29
  class SessionOverflowError < ActionControllerError #:nodoc:
30
30
  DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
31
+
32
+ def initialize(message = nil)
33
+ super(message || DEFAULT_MESSAGE)
34
+ end
31
35
  end
32
36
  class DoubleRenderError < ActionControllerError #:nodoc:
33
37
  DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\". Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so \"render(...) and return false\"."
34
38
 
35
- def initialize(message=nil)
39
+ def initialize(message = nil)
36
40
  super(message || DEFAULT_MESSAGE)
37
41
  end
38
42
  end
@@ -455,9 +459,12 @@ module ActionController #:nodoc:
455
459
  self.class.controller_name
456
460
  end
457
461
 
462
+ def session_enabled?
463
+ request.session_options[:disabled] != false
464
+ end
465
+
458
466
  protected
459
- # Renders the content that'll be returned to the browser as the response body. This can just be as regular text, but is
460
- # more often the compilation of a template.
467
+ # Renders the content that will be returned to the browser as the response body.
461
468
  #
462
469
  # === Rendering an action
463
470
  #
@@ -517,14 +524,19 @@ module ActionController #:nodoc:
517
524
  #
518
525
  # === Rendering a file
519
526
  #
520
- # File rendering works just like action rendering except that it takes an absolute path.
521
- # The current layout is not applied automatically.
527
+ # File rendering works just like action rendering except that it takes a filesystem path. By default, the path
528
+ # is assumed to be absolute, and the current layout is not applied.
529
+ #
530
+ # # Renders the template located at the absolute filesystem path
531
+ # render :file => "/path/to/some/template.rhtml"
532
+ # render :file => "c:/path/to/some/template.rhtml"
522
533
  #
523
- # # Renders the template located in /path/to/some/template.r(html|xml)
524
- # render :file => "/path/to/some/template"
534
+ # # Renders a template within the current layout, and with a 404 status code
535
+ # render :file => "/path/to/some/template.rhtml", :layout => true, :status => 404
536
+ # render :file => "c:/path/to/some/template.rhtml", :layout => true, :status => 404
525
537
  #
526
- # # Renders the same template within the current layout, but with a 404 status code
527
- # render :file => "/path/to/some/template", :layout => true, :status => 404
538
+ # # Renders a template relative to the template root and chooses the proper file extension
539
+ # render :file => "some/template", :use_full_path => true
528
540
  #
529
541
  # _Deprecation_ _notice_: This used to have the signature <tt>render_file(path, status = 200)</tt>
530
542
  #
@@ -588,7 +600,7 @@ module ActionController #:nodoc:
588
600
 
589
601
  else
590
602
  if file = options[:file]
591
- render_file(file, options[:status], options[:use_full_path])
603
+ render_file(file, options[:status], options[:use_full_path], options[:locals] || {})
592
604
 
593
605
  elsif template = options[:template]
594
606
  render_file(template, options[:status], true)
@@ -636,11 +648,11 @@ module ActionController #:nodoc:
636
648
  end
637
649
  end
638
650
 
639
- def render_file(template_path, status = nil, use_full_path = false)
651
+ def render_file(template_path, status = nil, use_full_path = false, locals = {})
640
652
  add_variables_to_assigns
641
653
  assert_existance_of_template_file(template_path) if use_full_path
642
654
  logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger
643
- render_text(@template.render_file(template_path, use_full_path), status)
655
+ render_text(@template.render_file(template_path, use_full_path, locals), status)
644
656
  end
645
657
 
646
658
  def render_template(template, status = nil, type = :rhtml, local_assigns = {})
@@ -236,6 +236,7 @@ module ActionController #:nodoc:
236
236
  # * DRbStore: Keeps the fragments in the memory of a separate, shared DRb process. This works for all environments and only keeps one cache
237
237
  # around for all processes, but requires that you run and manage a separate DRb process.
238
238
  # * MemCacheStore: Works like DRbStore, but uses Danga's MemCache instead.
239
+ # Requires the ruby-memcache library: gem install ruby-memcache.
239
240
  #
240
241
  # Configuration examples (MemoryStore is the default):
241
242
  #
@@ -54,6 +54,7 @@ class CGI #:nodoc:
54
54
  content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) || ''
55
55
  # fix for Safari Ajax postings that always append \000
56
56
  content.chop! if content[-1] == 0
57
+ content.gsub! /&_=$/, ''
57
58
  env_table['RAW_POST_DATA'] = content.freeze
58
59
  end
59
60
 
@@ -89,37 +89,28 @@ module ActionController #:nodoc:
89
89
  def port_from_http_host
90
90
  $1.to_i if env['HTTP_HOST'] && /:(\d+)$/ =~ env['HTTP_HOST']
91
91
  end
92
-
93
- def session
94
- return @session unless @session.nil?
95
92
 
96
- begin
97
- @session = (@session_options == false ? {} : CGI::Session.new(@cgi, session_options_with_string_keys))
98
- @session["__valid_session"]
99
- return @session
100
- rescue ArgumentError => e
101
- if e.message =~ %r{undefined class/module (\w+)}
102
- begin
103
- Module.const_missing($1)
104
- rescue LoadError, NameError => e
105
- raise(
106
- ActionController::SessionRestoreError,
107
- "Session contained objects where the class definition wasn't available. " +
108
- "Remember to require classes for all objects kept in the session. " +
109
- "(Original exception: #{e.message} [#{e.class}])"
110
- )
111
- end
112
-
113
- retry
93
+ def session
94
+ unless @session
95
+ if @session_options == false
96
+ @session = Hash.new
114
97
  else
115
- raise
98
+ stale_session_check! do
99
+ if session_options_with_string_keys['new_session'] == true
100
+ @session = new_session
101
+ else
102
+ @session = CGI::Session.new(@cgi, session_options_with_string_keys)
103
+ end
104
+ @session['__valid_session']
105
+ end
116
106
  end
117
107
  end
108
+ @session
118
109
  end
119
-
110
+
120
111
  def reset_session
121
112
  @session.delete if CGI::Session === @session
122
- @session = (@session_options == false ? {} : new_session)
113
+ @session = new_session
123
114
  end
124
115
 
125
116
  def method_missing(method_id, *arguments)
@@ -127,12 +118,38 @@ module ActionController #:nodoc:
127
118
  end
128
119
 
129
120
  private
121
+ # Delete an old session if it exists then create a new one.
130
122
  def new_session
131
- CGI::Session.new(@cgi, session_options_with_string_keys.update("new_session" => true))
123
+ if @session_options == false
124
+ Hash.new
125
+ else
126
+ CGI::Session.new(@cgi, session_options_with_string_keys.merge("new_session" => false)).delete rescue nil
127
+ CGI::Session.new(@cgi, session_options_with_string_keys.merge("new_session" => true))
128
+ end
132
129
  end
133
-
130
+
131
+ def stale_session_check!
132
+ yield
133
+ rescue ArgumentError => argument_error
134
+ if argument_error.message =~ %r{undefined class/module (\w+)}
135
+ begin
136
+ Module.const_missing($1)
137
+ rescue LoadError, NameError => const_error
138
+ raise ActionController::SessionRestoreError, <<end_msg
139
+ Session contains objects whose class definition isn't available.
140
+ Remember to require the classes for all objects kept in the session.
141
+ (Original exception: #{const_error.message} [#{const_error.class}])
142
+ end_msg
143
+ end
144
+
145
+ retry
146
+ else
147
+ raise
148
+ end
149
+ end
150
+
134
151
  def session_options_with_string_keys
135
- DEFAULT_SESSION_OPTIONS.merge(@session_options).inject({}) { |options, (k,v)| options[k.to_s] = v; options }
152
+ @session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).inject({}) { |options, (k,v)| options[k.to_s] = v; options }
136
153
  end
137
154
  end
138
155
 
@@ -52,11 +52,11 @@ module ActionController #:nodoc:
52
52
  def component_response(options, reuse_response = true)
53
53
  begin
54
54
  ActionController::Flash::FlashHash.avoid_sweep = true
55
- Thread.current[:p] = component_class(options).process(request_for_component(options), reuse_response ? @response : response_for_component)
55
+ p = component_class(options).process(request_for_component(options), reuse_response ? @response : response_for_component)
56
56
  ensure
57
57
  ActionController::Flash::FlashHash.avoid_sweep = false
58
58
  end
59
- Thread.current[:p]
59
+ p
60
60
  end
61
61
 
62
62
  def component_class(options)
@@ -132,22 +132,31 @@ module ActionController #:nodoc:
132
132
  end
133
133
  end
134
134
  end
135
-
136
-
135
+
136
+
137
137
  protected
138
138
  # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or
139
139
  # <tt>flash["notice"] = "hello"</tt> to put a new one.
140
+ # Note that if sessions are disabled only flash.now will work.
140
141
  def flash #:doc:
141
- @session['flash'] ||= FlashHash.new
142
+ # @session = Hash.new if sessions are disabled
143
+ if @session.is_a?(Hash)
144
+ @__flash ||= FlashHash.new
145
+
146
+ # otherwise, @session is a CGI::Session or a TestSession
147
+ else
148
+ @session['flash'] ||= FlashHash.new
149
+ end
142
150
  end
143
-
151
+
144
152
  # deprecated. use <tt>flash.keep</tt> instead
145
153
  def keep_flash #:doc:
154
+ warn 'keep_flash is deprecated; use flash.keep instead.'
146
155
  flash.keep
147
156
  end
148
-
149
-
150
- private
157
+
158
+
159
+ private
151
160
 
152
161
  # marks flash entries as used and expose the flash to the view
153
162
  def fire_flash
@@ -108,12 +108,23 @@ module ActionController #:nodoc:
108
108
  end
109
109
 
110
110
  private
111
+ def default_helper_module!
112
+ module_name = name.sub(/^Controllers::/, '').sub(/Controller$|$/, 'Helper')
113
+ module_path = module_name.split('::').map { |m| m.underscore }.join('/')
114
+ require_dependency module_path
115
+ helper module_name.constantize
116
+ rescue LoadError
117
+ logger.debug("#{name}: missing default helper path #{module_path}") if logger
118
+ rescue NameError
119
+ logger.debug("#{name}: missing default helper module #{module_name}") if logger
120
+ end
121
+
111
122
  def inherited_with_helper(child)
112
123
  inherited_without_helper(child)
113
124
  begin
114
125
  child.master_helper_module = Module.new
115
126
  child.master_helper_module.send :include, master_helper_module
116
- child.helper child.controller_path
127
+ child.send :default_helper_module!
117
128
  rescue MissingSourceFile => e
118
129
  raise unless e.is_missing?("helpers/#{child.controller_path}_helper")
119
130
  end
@@ -66,7 +66,9 @@ module ActionController #:nodoc:
66
66
  # <tt>app/views/layouts/weblog.rhtml</tt> or <tt>app/views/layouts/weblog.rxml</tt> exists then it will be automatically set as
67
67
  # the layout for your WeblogController. You can create a layout with the name <tt>application.rhtml</tt> or <tt>application.rxml</tt>
68
68
  # and this will be set as the default controller if there is no layout with the same name as the current controller and there is
69
- # no layout explicitly assigned with the +layout+ method. Setting a layout explicitly will always override the automatic behaviour.
69
+ # no layout explicitly assigned with the +layout+ method. Setting a layout explicitly will always override the automatic behaviour
70
+ # for the controller where the layout is set. Explicitly setting the layout in a parent class, though, will not override the
71
+ # child class's layout assignement if the child class has a layout with the same name.
70
72
  #
71
73
  # == Inheritance for layouts
72
74
  #
@@ -14,7 +14,7 @@ module ActionController
14
14
  # end
15
15
  #
16
16
  # # View
17
- # <%= in_place_editor_field :post, title %>
17
+ # <%= in_place_editor_field :post, 'title' %>
18
18
  #
19
19
  # For help on defining an in place editor in the browser,
20
20
  # see ActionView::Helpers::JavaScriptHelper.
@@ -2,7 +2,7 @@ module ActionController
2
2
  # These methods are available in both the production and test Request objects.
3
3
  class AbstractRequest
4
4
  cattr_accessor :relative_url_root
5
-
5
+
6
6
  # Returns both GET and POST parameters in a single hash.
7
7
  def parameters
8
8
  @parameters ||= request_parameters.merge(query_parameters).merge(path_parameters).with_indifferent_access
@@ -110,7 +110,7 @@ module ActionController
110
110
  # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
111
111
  def domain(tld_length = 1)
112
112
  return nil if !/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/.match(host).nil? or host.nil?
113
-
113
+
114
114
  host.split('.').last(1 + tld_length).join('.')
115
115
  end
116
116
 
@@ -123,13 +123,13 @@ module ActionController
123
123
  parts[0..-(tld_length+2)]
124
124
  end
125
125
 
126
- # Receive the raw post data.
127
- # This is useful for services such as REST, XMLRPC and SOAP
128
- # which communicate over HTTP POST but don't use the traditional parameter format.
126
+ # Receive the raw post data.
127
+ # This is useful for services such as REST, XMLRPC and SOAP
128
+ # which communicate over HTTP POST but don't use the traditional parameter format.
129
129
  def raw_post
130
130
  env['RAW_POST_DATA']
131
131
  end
132
-
132
+
133
133
  # Returns the request URI correctly, taking into account the idiosyncracies
134
134
  # of the various servers.
135
135
  def request_uri
@@ -153,9 +153,9 @@ module ActionController
153
153
 
154
154
  # Is this an SSL request?
155
155
  def ssl?
156
- env['HTTPS'] == 'on'
156
+ env['HTTPS'] == 'on'
157
157
  end
158
-
158
+
159
159
  # Returns the interpreted path to requested resource after all the installation directory of this application was taken into account
160
160
  def path
161
161
  path = (uri = request_uri) ? uri.split('?').first : ''
@@ -165,18 +165,19 @@ module ActionController
165
165
  path[0, root.length] = '' if root
166
166
  path || ''
167
167
  end
168
-
168
+
169
169
  # Returns the path minus the web server relative installation directory.
170
170
  # This method returns nil unless the web server is apache.
171
171
  def relative_url_root
172
- @@relative_url_root ||= server_software == 'apache' ? File.dirname(env["SCRIPT_NAME"].to_s).gsub(/(^\.$|^\/$)/, '') : ''
172
+ @@relative_url_root ||= server_software == 'apache' ? env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)$/, '') : ''
173
+
173
174
  end
174
175
 
175
176
  # Returns the port number of this request as an integer.
176
177
  def port
177
178
  @port_as_int ||= env['SERVER_PORT'].to_i
178
179
  end
179
-
180
+
180
181
  # Returns the standard port number for this request's protocol
181
182
  def standard_port
182
183
  case protocol
@@ -196,12 +197,12 @@ module ActionController
196
197
  def host_with_port
197
198
  host + port_string
198
199
  end
199
-
200
+
200
201
  def path_parameters=(parameters)
201
202
  @path_parameters = parameters
202
203
  @symbolized_path_parameters = @parameters = nil
203
204
  end
204
-
205
+
205
206
  def symbolized_path_parameters
206
207
  @symbolized_path_parameters ||= path_parameters.symbolize_keys
207
208
  end
@@ -224,10 +225,13 @@ module ActionController
224
225
  def request_parameters #:nodoc:
225
226
  end
226
227
 
227
- def env #:nodoc:
228
+ # Returns the hash of environment variables for this request,
229
+ # such as { 'RAILS_ENV' => 'production' }.
230
+ def env
228
231
  end
229
232
 
230
- def host #:nodoc:
233
+ # Returns the host for this request, such as example.com.
234
+ def host
231
235
  end
232
236
 
233
237
  def cookies #:nodoc:
@@ -237,6 +241,6 @@ module ActionController
237
241
  end
238
242
 
239
243
  def reset_session #:nodoc:
240
- end
244
+ end
241
245
  end
242
246
  end