actionpack 3.2.8 → 3.2.9.rc1

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.

@@ -309,7 +309,7 @@ module AbstractController
309
309
  # still does a dynamic lookup. In next Rails release, we should @_layout
310
310
  # to be inheritable so we can skip the child lookup if the parent explicitly
311
311
  # set the layout.
312
- parent = self.superclass.instance_variable_get(:@_layout)
312
+ parent = self.superclass.instance_eval { @_layout if defined?(@_layout) }
313
313
  @_layout = nil
314
314
  inspect = parent.is_a?(Proc) ? parent.inspect : parent
315
315
 
@@ -20,7 +20,8 @@ module ActionController
20
20
 
21
21
  status = payload[:status]
22
22
  if status.nil? && payload[:exception].present?
23
- status = Rack::Utils.status_code(ActionDispatch::ExceptionWrapper.new({}, payload[:exception]).status_code)
23
+ exception_class_name = payload[:exception].first
24
+ status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
24
25
  end
25
26
  message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.0fms" % event.duration
26
27
  message << " (#{additions.join(" | ")})" unless additions.blank?
@@ -75,7 +75,27 @@ module ActionController #:nodoc:
75
75
 
76
76
  self.status = options[:status] || 200
77
77
  self.content_type = options[:content_type] if options.key?(:content_type)
78
- self.response_body = File.open(path, "rb")
78
+ self.response_body = FileBody.new(path)
79
+ end
80
+
81
+ # Avoid having to pass an open file handle as the response body.
82
+ # Rack::Sendfile will usually intercept the response and uses
83
+ # the path directly, so there is no reason to open the file.
84
+ class FileBody #:nodoc:
85
+ attr_reader :to_path
86
+
87
+ def initialize(path)
88
+ @to_path = path
89
+ end
90
+
91
+ # Stream the file's contents if Rack::Sendfile isn't present.
92
+ def each
93
+ File.open(to_path, 'rb') do |file|
94
+ while chunk = file.read(16384)
95
+ yield chunk
96
+ end
97
+ end
98
+ end
79
99
  end
80
100
 
81
101
  # Sends the given binary data to the browser. This method is similar to
@@ -115,7 +135,7 @@ module ActionController #:nodoc:
115
135
  private
116
136
  def send_file_headers!(options)
117
137
  type_provided = options.has_key?(:type)
118
-
138
+
119
139
  options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
120
140
  [:type, :disposition].each do |arg|
121
141
  raise ArgumentError, ":#{arg} option required" if options[arg].nil?
@@ -14,13 +14,13 @@ module ActionController
14
14
  end
15
15
 
16
16
  def setup_subscriptions
17
- @partials = Hash.new(0)
18
- @templates = Hash.new(0)
19
- @layouts = Hash.new(0)
17
+ @_partials = Hash.new(0)
18
+ @_templates = Hash.new(0)
19
+ @_layouts = Hash.new(0)
20
20
 
21
21
  ActiveSupport::Notifications.subscribe("render_template.action_view") do |name, start, finish, id, payload|
22
22
  path = payload[:layout]
23
- @layouts[path] += 1
23
+ @_layouts[path] += 1
24
24
  end
25
25
 
26
26
  ActiveSupport::Notifications.subscribe("!render_template.action_view") do |name, start, finish, id, payload|
@@ -28,11 +28,11 @@ module ActionController
28
28
  next unless path
29
29
  partial = path =~ /^.*\/_[^\/]*$/
30
30
  if partial
31
- @partials[path] += 1
32
- @partials[path.split("/").last] += 1
33
- @templates[path] += 1
31
+ @_partials[path] += 1
32
+ @_partials[path.split("/").last] += 1
33
+ @_templates[path] += 1
34
34
  else
35
- @templates[path] += 1
35
+ @_templates[path] += 1
36
36
  end
37
37
  end
38
38
  end
@@ -43,9 +43,9 @@ module ActionController
43
43
  end
44
44
 
45
45
  def process(*args)
46
- @partials = Hash.new(0)
47
- @templates = Hash.new(0)
48
- @layouts = Hash.new(0)
46
+ @_partials = Hash.new(0)
47
+ @_templates = Hash.new(0)
48
+ @_layouts = Hash.new(0)
49
49
  super
50
50
  end
51
51
 
@@ -72,43 +72,54 @@ module ActionController
72
72
  validate_request!
73
73
 
74
74
  case options
75
- when NilClass, String, Symbol
75
+ when NilClass, Regexp, String, Symbol
76
76
  options = options.to_s if Symbol === options
77
- rendered = @templates
77
+ rendered = @_templates
78
78
  msg = build_message(message,
79
79
  "expecting <?> but rendering with <?>",
80
80
  options, rendered.keys.join(', '))
81
- assert_block(msg) do
82
- if options
81
+ matches_template =
82
+ case options
83
+ when String
84
+ rendered.any? do |t, num|
85
+ options_splited = options.split(File::SEPARATOR)
86
+ t_splited = t.split(File::SEPARATOR)
87
+ t_splited.last(options_splited.size) == options_splited
88
+ end
89
+ when Regexp
83
90
  rendered.any? { |t,num| t.match(options) }
84
- else
85
- @templates.blank?
91
+ when NilClass
92
+ rendered.blank?
86
93
  end
87
- end
94
+ assert matches_template, msg
88
95
  when Hash
89
96
  if expected_layout = options[:layout]
90
97
  msg = build_message(message,
91
98
  "expecting layout <?> but action rendered <?>",
92
- expected_layout, @layouts.keys)
99
+ expected_layout, @_layouts.keys)
93
100
 
94
101
  case expected_layout
95
102
  when String
96
- assert(@layouts.keys.include?(expected_layout), msg)
103
+ assert(@_layouts.keys.include?(expected_layout), msg)
97
104
  when Regexp
98
- assert(@layouts.keys.any? {|l| l =~ expected_layout }, msg)
105
+ assert(@_layouts.keys.any? {|l| l =~ expected_layout }, msg)
99
106
  when nil
100
- assert(@layouts.empty?, msg)
107
+ assert(@_layouts.empty?, msg)
101
108
  end
102
109
  end
103
110
 
104
111
  if expected_partial = options[:partial]
105
112
  if expected_locals = options[:locals]
106
- actual_locals = @locals[expected_partial.to_s.sub(/^_/,'')]
107
- expected_locals.each_pair do |k,v|
108
- assert_equal(v, actual_locals[k])
113
+ if defined?(@locals)
114
+ actual_locals = @locals[expected_partial.to_s.sub(/^_/,'')]
115
+ expected_locals.each_pair do |k,v|
116
+ assert_equal(v, actual_locals[k])
117
+ end
118
+ else
119
+ warn "the :locals option to #assert_template is only supported in a ActionView::TestCase"
109
120
  end
110
121
  elsif expected_count = options[:count]
111
- actual_count = @partials[expected_partial]
122
+ actual_count = @_partials[expected_partial]
112
123
  msg = build_message(message,
113
124
  "expecting ? to be rendered ? time(s) but rendered ? time(s)",
114
125
  expected_partial, expected_count, actual_count)
@@ -116,11 +127,11 @@ module ActionController
116
127
  else
117
128
  msg = build_message(message,
118
129
  "expecting partial <?> but action rendered <?>",
119
- options[:partial], @partials.keys)
120
- assert(@partials.include?(expected_partial), msg)
130
+ options[:partial], @_partials.keys)
131
+ assert(@_partials.include?(expected_partial), msg)
121
132
  end
122
133
  else
123
- assert @partials.empty?,
134
+ assert @_partials.empty?,
124
135
  "Expected no partials to be rendered"
125
136
  end
126
137
  end
@@ -422,7 +433,7 @@ module ActionController
422
433
  Hash[hash_or_array_or_value.map{|key, value| [key, paramify_values(value)] }]
423
434
  when Array
424
435
  hash_or_array_or_value.map {|i| paramify_values(i)}
425
- when Rack::Test::UploadedFile
436
+ when Rack::Test::UploadedFile, ActionDispatch::Http::UploadedFile
426
437
  hash_or_array_or_value
427
438
  else
428
439
  hash_or_array_or_value.to_param
@@ -19,7 +19,7 @@ module ActionDispatch
19
19
  [:open, :path, :rewind, :size].each do |method|
20
20
  class_eval "def #{method}; @tempfile.#{method}; end"
21
21
  end
22
-
22
+
23
23
  private
24
24
  def encode_filename(filename)
25
25
  # Encode the filename in the utf8 encoding, unless it is nil or we're in 1.8
@@ -170,12 +170,14 @@ module ActionDispatch
170
170
  options = { :value => value }
171
171
  end
172
172
 
173
- @cookies[key.to_s] = value
174
-
175
173
  handle_options(options)
176
174
 
177
- @set_cookies[key.to_s] = options
178
- @delete_cookies.delete(key.to_s)
175
+ if @cookies[key.to_s] != value or options[:expires]
176
+ @cookies[key.to_s] = value
177
+ @set_cookies[key.to_s] = options
178
+ @delete_cookies.delete(key.to_s)
179
+ end
180
+
179
181
  value
180
182
  end
181
183
 
@@ -34,7 +34,7 @@ module ActionDispatch
34
34
  end
35
35
 
36
36
  def status_code
37
- Rack::Utils.status_code(@@rescue_responses[@exception.class.name])
37
+ self.class.status_code_for_exception(@exception.class.name)
38
38
  end
39
39
 
40
40
  def application_trace
@@ -49,6 +49,10 @@ module ActionDispatch
49
49
  clean_backtrace(:all)
50
50
  end
51
51
 
52
+ def self.status_code_for_exception(class_name)
53
+ Rack::Utils.status_code(@@rescue_responses[class_name])
54
+ end
55
+
52
56
  private
53
57
 
54
58
  def original_exception(exception)
@@ -75,4 +79,4 @@ module ActionDispatch
75
79
  @backtrace_cleaner ||= @env['action_dispatch.backtrace_cleaner']
76
80
  end
77
81
  end
78
- end
82
+ end
@@ -74,6 +74,13 @@ module ActionDispatch
74
74
  class AbstractStore < Rack::Session::Abstract::ID
75
75
  include Compatibility
76
76
  include StaleSessionCheck
77
+
78
+ private
79
+
80
+ def set_cookie(env, session_id, cookie)
81
+ request = ActionDispatch::Request.new(env)
82
+ request.cookie_jar[key] = cookie
83
+ end
77
84
  end
78
85
  end
79
86
  end
@@ -166,7 +166,7 @@ module ActionDispatch
166
166
  controller ||= default_controller
167
167
  action ||= default_action
168
168
 
169
- unless controller.is_a?(Regexp) || to_shorthand
169
+ unless controller.is_a?(Regexp)
170
170
  controller = [@scope[:module], controller].compact.join("/").presence
171
171
  end
172
172
 
@@ -982,7 +982,7 @@ module ActionDispatch
982
982
  # === Options
983
983
  # Takes same options as +resources+.
984
984
  def resource(*resources, &block)
985
- options = resources.extract_options!
985
+ options = resources.extract_options!.dup
986
986
 
987
987
  if apply_common_behavior_for(:resource, resources, options, &block)
988
988
  return self
@@ -1120,7 +1120,7 @@ module ActionDispatch
1120
1120
  # # resource actions are at /admin/posts.
1121
1121
  # resources :posts, :path => "admin/posts"
1122
1122
  def resources(*resources, &block)
1123
- options = resources.extract_options!
1123
+ options = resources.extract_options!.dup
1124
1124
 
1125
1125
  if apply_common_behavior_for(:resources, resources, options, &block)
1126
1126
  return self
@@ -18,8 +18,8 @@ module ActionDispatch
18
18
  # a Hash, or a String that is appropriately encoded
19
19
  # (<tt>application/x-www-form-urlencoded</tt> or
20
20
  # <tt>multipart/form-data</tt>).
21
- # - +headers+: Additional HTTP headers to pass, as a Hash. The keys will
22
- # automatically be upcased, with the prefix 'HTTP_' added if needed.
21
+ # - +headers+: Additional headers to pass, as a Hash. The headers will be
22
+ # merged into the Rack env hash.
23
23
  #
24
24
  # This method returns an Response object, which one can use to
25
25
  # inspect the details of the response. Furthermore, if this method was
@@ -62,8 +62,7 @@ module ActionDispatch
62
62
  #
63
63
  # The request_method is +:get+, +:post+, +:put+, +:delete+ or +:head+; the
64
64
  # parameters are +nil+, a hash, or a url-encoded or multipart string;
65
- # the headers are a hash. Keys are automatically upcased and prefixed
66
- # with 'HTTP_' if not already.
65
+ # the headers are a hash.
67
66
  def xml_http_request(request_method, path, parameters = nil, headers = nil)
68
67
  headers ||= {}
69
68
  headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
@@ -12,7 +12,7 @@ module ActionDispatch
12
12
  end
13
13
 
14
14
  def initialize(env = {})
15
- env = Rails.application.env_config.merge(env) if defined?(Rails.application)
15
+ env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
16
16
  super(DEFAULT_ENV.merge(env))
17
17
 
18
18
  self.host = 'test.host'
@@ -2,8 +2,8 @@ module ActionPack
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
- TINY = 8
6
- PRE = nil
5
+ TINY = 9
6
+ PRE = "rc1"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
@@ -27,7 +27,8 @@ module ActionView
27
27
 
28
28
  def expand_sources(sources, recursive = false)
29
29
  if sources.include?(:all)
30
- all_asset_files = (collect_asset_files(custom_dir, ('**' if recursive), "*.#{extension}") - ['application']) << 'application'
30
+ all_asset_files = (collect_asset_files(custom_dir, ('**' if recursive), "*.#{extension}") - ['application'])
31
+ add_application_js(all_asset_files, sources)
31
32
  ((determine_source(:defaults, expansions).dup & all_asset_files) + all_asset_files).uniq
32
33
  else
33
34
  expanded_sources = sources.inject([]) do |list, source|
@@ -40,7 +41,7 @@ module ActionView
40
41
  end
41
42
 
42
43
  def add_application_js(expanded_sources, sources)
43
- if sources.include?(:defaults) && File.exist?(File.join(custom_dir, "application.#{extension}"))
44
+ if (sources.include?(:defaults) || sources.include?(:all)) && File.exist?(File.join(custom_dir, "application.#{extension}"))
44
45
  expanded_sources.delete('application')
45
46
  expanded_sources << "application"
46
47
  end
@@ -101,8 +102,8 @@ module ActionView
101
102
  #
102
103
  # config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js)
103
104
  #
104
- # When using <tt>:defaults</tt>, if an <tt>application.js</tt> file exists in
105
- # <tt>public/javascripts</tt> it will be included as well at the end.
105
+ # When using <tt>:defaults</tt> or <tt>:all</tt>, if an <tt>application.js</tt> file exists
106
+ # in <tt>public/javascripts</tt> it will be included as well at the end.
106
107
  #
107
108
  # You can modify the HTML attributes of the script tag by passing a hash as the
108
109
  # last argument.
@@ -129,16 +130,16 @@ module ActionView
129
130
  # # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
130
131
  # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
131
132
  #
132
- # * = The application.js file is only referenced if it exists
133
+ # Note: The application.js file is only referenced if it exists
133
134
  #
134
135
  # You can also include all JavaScripts in the +javascripts+ directory using <tt>:all</tt> as the source:
135
136
  #
136
137
  # javascript_include_tag :all
137
138
  # # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
138
139
  # # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
139
- # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
140
140
  # # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
141
141
  # # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
142
+ # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
142
143
  #
143
144
  # Note that your defaults of choice will be included first, so they will be available to all subsequently
144
145
  # included files.
@@ -161,9 +162,9 @@ module ActionView
161
162
  # javascript_include_tag :all, :cache => true
162
163
  # # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
163
164
  # # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
164
- # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
165
165
  # # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
166
166
  # # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
167
+ # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
167
168
  #
168
169
  # # assuming config.perform_caching is true
169
170
  # javascript_include_tag :all, :cache => true
@@ -915,12 +915,15 @@ module ActionView
915
915
  # build_hidden(:year, 2008)
916
916
  # => "<input id="post_written_on_1i" name="post[written_on(1i)]" type="hidden" value="2008" />"
917
917
  def build_hidden(type, value)
918
- (tag(:input, {
918
+ select_options = {
919
919
  :type => "hidden",
920
920
  :id => input_id_from_type(type),
921
921
  :name => input_name_from_type(type),
922
922
  :value => value
923
- }.merge(@html_options.slice(:disabled))) + "\n").html_safe
923
+ }.merge(@html_options.slice(:disabled))
924
+ select_options.merge!(:disabled => 'disabled') if @options[:disabled]
925
+
926
+ tag(:input, select_options) + "\n".html_safe
924
927
  end
925
928
 
926
929
  # Returns the name attribute for the input tag.
@@ -119,6 +119,7 @@ module ActionView
119
119
  # # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
120
120
  # # <option>Paris</option><option>Rome</option></select>
121
121
  def select_tag(name, option_tags = nil, options = {})
122
+ option_tags ||= ""
122
123
  html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
123
124
 
124
125
  if options.delete(:include_blank)
@@ -633,7 +633,9 @@ module ActionView
633
633
  end
634
634
 
635
635
  def link_to_remote_options?(options)
636
- options.is_a?(Hash) && options.key?('remote') && options.delete('remote')
636
+ if options.is_a?(Hash)
637
+ options.delete('remote') || options.delete(:remote)
638
+ end
637
639
  end
638
640
 
639
641
  def add_method_to_attributes!(html_options, method)
@@ -193,16 +193,16 @@ module ActionView
193
193
  @_result
194
194
  @_routes
195
195
  @controller
196
- @layouts
196
+ @_layouts
197
197
  @locals
198
198
  @method_name
199
199
  @output_buffer
200
- @partials
200
+ @_partials
201
201
  @passed
202
202
  @rendered
203
203
  @request
204
204
  @routes
205
- @templates
205
+ @_templates
206
206
  @options
207
207
  @test_passed
208
208
  @view