actionpack 2.0.5 → 2.1.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.
- data/CHANGELOG +149 -7
- data/MIT-LICENSE +1 -1
- data/README +1 -1
- data/Rakefile +5 -6
- data/lib/action_controller.rb +2 -2
- data/lib/action_controller/assertions/model_assertions.rb +2 -1
- data/lib/action_controller/assertions/response_assertions.rb +4 -2
- data/lib/action_controller/assertions/routing_assertions.rb +3 -3
- data/lib/action_controller/assertions/selector_assertions.rb +30 -27
- data/lib/action_controller/assertions/tag_assertions.rb +3 -3
- data/lib/action_controller/base.rb +103 -129
- data/lib/action_controller/benchmarking.rb +3 -3
- data/lib/action_controller/caching.rb +41 -652
- data/lib/action_controller/caching/actions.rb +144 -0
- data/lib/action_controller/caching/fragments.rb +138 -0
- data/lib/action_controller/caching/pages.rb +154 -0
- data/lib/action_controller/caching/sql_cache.rb +18 -0
- data/lib/action_controller/caching/sweeping.rb +97 -0
- data/lib/action_controller/cgi_ext/cookie.rb +27 -23
- data/lib/action_controller/cgi_ext/stdinput.rb +1 -0
- data/lib/action_controller/cgi_process.rb +6 -4
- data/lib/action_controller/components.rb +7 -6
- data/lib/action_controller/cookies.rb +31 -19
- data/lib/action_controller/dispatcher.rb +51 -84
- data/lib/action_controller/filters.rb +295 -421
- data/lib/action_controller/flash.rb +1 -6
- data/lib/action_controller/headers.rb +31 -0
- data/lib/action_controller/helpers.rb +26 -9
- data/lib/action_controller/http_authentication.rb +1 -1
- data/lib/action_controller/integration.rb +65 -13
- data/lib/action_controller/layout.rb +24 -39
- data/lib/action_controller/mime_responds.rb +7 -3
- data/lib/action_controller/mime_type.rb +25 -9
- data/lib/action_controller/mime_types.rb +1 -1
- data/lib/action_controller/polymorphic_routes.rb +32 -17
- data/lib/action_controller/record_identifier.rb +10 -4
- data/lib/action_controller/request.rb +46 -30
- data/lib/action_controller/request_forgery_protection.rb +10 -9
- data/lib/action_controller/request_profiler.rb +29 -8
- data/lib/action_controller/rescue.rb +24 -24
- data/lib/action_controller/resources.rb +66 -23
- data/lib/action_controller/response.rb +2 -2
- data/lib/action_controller/routing.rb +113 -1229
- data/lib/action_controller/routing/builder.rb +204 -0
- data/lib/action_controller/{routing_optimisation.rb → routing/optimisations.rb} +13 -12
- data/lib/action_controller/routing/recognition_optimisation.rb +158 -0
- data/lib/action_controller/routing/route.rb +240 -0
- data/lib/action_controller/routing/route_set.rb +435 -0
- data/lib/action_controller/routing/routing_ext.rb +46 -0
- data/lib/action_controller/routing/segments.rb +283 -0
- data/lib/action_controller/session/active_record_store.rb +13 -8
- data/lib/action_controller/session/cookie_store.rb +20 -17
- data/lib/action_controller/session_management.rb +10 -3
- data/lib/action_controller/streaming.rb +45 -31
- data/lib/action_controller/test_case.rb +33 -23
- data/lib/action_controller/test_process.rb +39 -35
- data/lib/action_controller/url_rewriter.rb +18 -12
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +1 -1
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +11 -3
- data/lib/action_view/base.rb +73 -390
- data/lib/action_view/helpers/active_record_helper.rb +83 -62
- data/lib/action_view/helpers/asset_tag_helper.rb +101 -44
- data/lib/action_view/helpers/atom_feed_helper.rb +35 -7
- data/lib/action_view/helpers/benchmark_helper.rb +5 -3
- data/lib/action_view/helpers/cache_helper.rb +3 -2
- data/lib/action_view/helpers/capture_helper.rb +1 -2
- data/lib/action_view/helpers/date_helper.rb +104 -82
- data/lib/action_view/helpers/form_helper.rb +148 -75
- data/lib/action_view/helpers/form_options_helper.rb +44 -23
- data/lib/action_view/helpers/form_tag_helper.rb +22 -13
- data/lib/action_view/helpers/javascripts/controls.js +1 -1
- data/lib/action_view/helpers/javascripts/dragdrop.js +1 -1
- data/lib/action_view/helpers/javascripts/effects.js +1 -1
- data/lib/action_view/helpers/number_helper.rb +10 -3
- data/lib/action_view/helpers/prototype_helper.rb +61 -29
- data/lib/action_view/helpers/record_tag_helper.rb +3 -3
- data/lib/action_view/helpers/sanitize_helper.rb +23 -17
- data/lib/action_view/helpers/scriptaculous_helper.rb +86 -60
- data/lib/action_view/helpers/text_helper.rb +153 -125
- data/lib/action_view/helpers/url_helper.rb +83 -28
- data/lib/action_view/inline_template.rb +20 -0
- data/lib/action_view/partial_template.rb +70 -0
- data/lib/action_view/partials.rb +31 -73
- data/lib/action_view/template.rb +127 -0
- data/lib/action_view/template_error.rb +8 -7
- data/lib/action_view/template_finder.rb +177 -0
- data/lib/action_view/template_handler.rb +18 -1
- data/lib/action_view/template_handlers/builder.rb +10 -2
- data/lib/action_view/template_handlers/compilable.rb +128 -0
- data/lib/action_view/template_handlers/erb.rb +37 -2
- data/lib/action_view/template_handlers/rjs.rb +14 -1
- data/lib/action_view/test_case.rb +58 -0
- data/test/abstract_unit.rb +1 -1
- data/test/active_record_unit.rb +3 -6
- data/test/activerecord/active_record_store_test.rb +1 -2
- data/test/activerecord/render_partial_with_record_identification_test.rb +158 -41
- data/test/adv_attr_test.rb +20 -0
- data/test/controller/action_pack_assertions_test.rb +16 -19
- data/test/controller/addresses_render_test.rb +1 -1
- data/test/controller/assert_select_test.rb +13 -6
- data/test/controller/base_test.rb +48 -2
- data/test/controller/benchmark_test.rb +1 -2
- data/test/controller/caching_test.rb +282 -21
- data/test/controller/capture_test.rb +1 -1
- data/test/controller/cgi_test.rb +1 -1
- data/test/controller/components_test.rb +1 -1
- data/test/controller/content_type_test.rb +2 -2
- data/test/controller/cookie_test.rb +13 -2
- data/test/controller/custom_handler_test.rb +14 -10
- data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -1
- data/test/controller/dispatcher_test.rb +31 -49
- data/test/controller/fake_controllers.rb +17 -0
- data/test/controller/fake_models.rb +6 -0
- data/test/controller/filter_params_test.rb +14 -8
- data/test/controller/filters_test.rb +44 -16
- data/test/controller/flash_test.rb +2 -2
- data/test/controller/header_test.rb +14 -0
- data/test/controller/helper_test.rb +19 -15
- data/test/controller/html-scanner/document_test.rb +1 -2
- data/test/controller/html-scanner/node_test.rb +1 -2
- data/test/controller/html-scanner/sanitizer_test.rb +8 -5
- data/test/controller/html-scanner/tag_node_test.rb +1 -2
- data/test/controller/html-scanner/text_node_test.rb +2 -3
- data/test/controller/html-scanner/tokenizer_test.rb +8 -2
- data/test/controller/http_authentication_test.rb +1 -1
- data/test/controller/integration_test.rb +14 -16
- data/test/controller/integration_upload_test.rb +43 -0
- data/test/controller/layout_test.rb +26 -6
- data/test/controller/mime_responds_test.rb +39 -7
- data/test/controller/mime_type_test.rb +29 -5
- data/test/controller/new_render_test.rb +105 -34
- data/test/controller/polymorphic_routes_test.rb +32 -20
- data/test/controller/record_identifier_test.rb +38 -2
- data/test/controller/redirect_test.rb +21 -1
- data/test/controller/render_test.rb +59 -15
- data/test/controller/request_forgery_protection_test.rb +92 -5
- data/test/controller/request_test.rb +64 -6
- data/test/controller/rescue_test.rb +22 -6
- data/test/controller/resources_test.rb +102 -14
- data/test/controller/routing_test.rb +231 -19
- data/test/controller/selector_test.rb +2 -2
- data/test/controller/send_file_test.rb +14 -3
- data/test/controller/session/cookie_store_test.rb +16 -4
- data/test/controller/session/mem_cache_store_test.rb +3 -4
- data/test/controller/session_fixation_test.rb +1 -1
- data/test/controller/session_management_test.rb +23 -1
- data/test/controller/test_test.rb +39 -18
- data/test/controller/url_rewriter_test.rb +35 -1
- data/test/controller/verification_test.rb +1 -1
- data/test/controller/view_paths_test.rb +15 -12
- data/test/controller/webservice_test.rb +48 -3
- data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
- data/test/fixtures/company.rb +1 -0
- data/test/fixtures/customers/_customer.html.erb +1 -0
- data/test/fixtures/db_definitions/sqlite.sql +6 -0
- data/test/fixtures/functional_caching/_partial.erb +3 -0
- data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
- data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
- data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
- data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
- data/test/fixtures/mascot.rb +3 -0
- data/test/fixtures/mascots.yml +4 -0
- data/test/fixtures/mascots/_mascot.html.erb +1 -0
- data/test/fixtures/multipart/boundary_problem_file +10 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/public/javascripts/controls.js +1 -0
- data/test/fixtures/public/javascripts/dragdrop.js +1 -0
- data/test/fixtures/public/javascripts/effects.js +1 -0
- data/test/fixtures/public/javascripts/prototype.js +1 -0
- data/test/fixtures/public/javascripts/version.1.0.js +1 -0
- data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
- data/test/fixtures/reply.rb +1 -0
- data/test/fixtures/shared.html.erb +1 -0
- data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
- data/test/fixtures/test/_customer_counter.erb +1 -0
- data/test/fixtures/test/_form.erb +1 -0
- data/test/fixtures/test/_labelling_form.erb +1 -0
- data/test/fixtures/test/_raise.html.erb +1 -0
- data/test/fixtures/test/greeting.js.rjs +1 -0
- data/test/fixtures/topics/_topic.html.erb +1 -0
- data/test/template/active_record_helper_test.rb +25 -8
- data/test/template/asset_tag_helper_test.rb +100 -17
- data/test/template/atom_feed_helper_test.rb +29 -1
- data/test/template/benchmark_helper_test.rb +10 -22
- data/test/template/date_helper_test.rb +455 -153
- data/test/template/erb_util_test.rb +10 -42
- data/test/template/form_helper_test.rb +192 -66
- data/test/template/form_options_helper_test.rb +19 -8
- data/test/template/form_tag_helper_test.rb +11 -8
- data/test/template/javascript_helper_test.rb +3 -9
- data/test/template/number_helper_test.rb +6 -3
- data/test/template/prototype_helper_test.rb +27 -40
- data/test/template/record_tag_helper_test.rb +54 -0
- data/test/template/sanitize_helper_test.rb +5 -6
- data/test/template/scriptaculous_helper_test.rb +7 -13
- data/test/template/tag_helper_test.rb +3 -6
- data/test/template/template_finder_test.rb +73 -0
- data/test/template/template_object_test.rb +95 -0
- data/test/template/test_test.rb +56 -0
- data/test/template/text_helper_test.rb +46 -33
- data/test/template/url_helper_test.rb +8 -10
- metadata +65 -12
- data/lib/action_view/compiled_templates.rb +0 -69
- data/test/action_view_test.rb +0 -44
- data/test/activerecord/fixtures_test.rb +0 -24
- data/test/controller/fragment_store_setting_test.rb +0 -47
- data/test/template/compiled_templates_test.rb +0 -197
- data/test/template/deprecate_ivars_test.rb +0 -51
@@ -28,7 +28,6 @@ module ActionController #:nodoc:
|
|
28
28
|
base.class_eval do
|
29
29
|
include InstanceMethods
|
30
30
|
alias_method_chain :assign_shortcuts, :flash
|
31
|
-
alias_method_chain :process_cleanup, :flash
|
32
31
|
alias_method_chain :reset_session, :flash
|
33
32
|
end
|
34
33
|
end
|
@@ -166,11 +165,7 @@ module ActionController #:nodoc:
|
|
166
165
|
def assign_shortcuts_with_flash(request, response) #:nodoc:
|
167
166
|
assign_shortcuts_without_flash(request, response)
|
168
167
|
flash(:refresh)
|
169
|
-
|
170
|
-
|
171
|
-
def process_cleanup_with_flash
|
172
|
-
flash.sweep if @_session
|
173
|
-
process_cleanup_without_flash
|
168
|
+
flash.sweep if @_session && !component_request?
|
174
169
|
end
|
175
170
|
end
|
176
171
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ActionController
|
2
|
+
module Http
|
3
|
+
class Headers < ::Hash
|
4
|
+
|
5
|
+
def initialize(constructor = {})
|
6
|
+
if constructor.is_a?(Hash)
|
7
|
+
super()
|
8
|
+
update(constructor)
|
9
|
+
else
|
10
|
+
super(constructor)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](header_name)
|
15
|
+
if include?(header_name)
|
16
|
+
super
|
17
|
+
else
|
18
|
+
super(normalize_header(header_name))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
# Takes an HTTP header name and returns it in the
|
25
|
+
# format
|
26
|
+
def normalize_header(header_name)
|
27
|
+
"HTTP_#{header_name.upcase.gsub(/-/, '_')}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -20,7 +20,7 @@ module ActionController #:nodoc:
|
|
20
20
|
end
|
21
21
|
|
22
22
|
# The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+,
|
23
|
-
# +numbers+ and
|
23
|
+
# +numbers+ and Active Record objects, to name a few. These helpers are available to all templates
|
24
24
|
# by default.
|
25
25
|
#
|
26
26
|
# In addition to using the standard template helpers provided in the Rails framework, creating custom helpers to
|
@@ -32,7 +32,7 @@ module ActionController #:nodoc:
|
|
32
32
|
# controller which inherits from it.
|
33
33
|
#
|
34
34
|
# ==== Examples
|
35
|
-
# The +to_s+ method from the
|
35
|
+
# The +to_s+ method from the Time class can be wrapped in a helper method to display a custom message if
|
36
36
|
# the Time object is blank:
|
37
37
|
#
|
38
38
|
# module FormattedTimeHelper
|
@@ -41,7 +41,7 @@ module ActionController #:nodoc:
|
|
41
41
|
# end
|
42
42
|
# end
|
43
43
|
#
|
44
|
-
#
|
44
|
+
# FormattedTimeHelper can now be included in a controller, using the +helper+ class method:
|
45
45
|
#
|
46
46
|
# class EventsController < ActionController::Base
|
47
47
|
# helper FormattedTimeHelper
|
@@ -74,22 +74,22 @@ module ActionController #:nodoc:
|
|
74
74
|
|
75
75
|
# The +helper+ class method can take a series of helper module names, a block, or both.
|
76
76
|
#
|
77
|
-
# * <tt>*args</tt>: One or more
|
77
|
+
# * <tt>*args</tt>: One or more modules, strings or symbols, or the special symbol <tt>:all</tt>.
|
78
78
|
# * <tt>&block</tt>: A block defining helper methods.
|
79
79
|
#
|
80
80
|
# ==== Examples
|
81
|
-
# When the argument is a
|
81
|
+
# When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
|
82
82
|
# and include the module in the template class. The second form illustrates how to include custom helpers
|
83
83
|
# when working with namespaced controllers, or other cases where the file containing the helper definition is not
|
84
84
|
# in one of Rails' standard load paths:
|
85
85
|
# helper :foo # => requires 'foo_helper' and includes FooHelper
|
86
86
|
# helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
|
87
87
|
#
|
88
|
-
# When the argument is a
|
88
|
+
# When the argument is a module it will be included directly in the template class.
|
89
89
|
# helper FooHelper # => includes FooHelper
|
90
90
|
#
|
91
91
|
# When the argument is the symbol <tt>:all</tt>, the controller will include all helpers from
|
92
|
-
# <tt>app/helpers/**/*.rb</tt> under
|
92
|
+
# <tt>app/helpers/**/*.rb</tt> under RAILS_ROOT.
|
93
93
|
# helper :all
|
94
94
|
#
|
95
95
|
# Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available
|
@@ -143,11 +143,19 @@ module ActionController #:nodoc:
|
|
143
143
|
# Declare a controller method as a helper. For example, the following
|
144
144
|
# makes the +current_user+ controller method available to the view:
|
145
145
|
# class ApplicationController < ActionController::Base
|
146
|
-
# helper_method :current_user
|
146
|
+
# helper_method :current_user, :logged_in?
|
147
|
+
#
|
147
148
|
# def current_user
|
148
|
-
# @current_user ||= User.
|
149
|
+
# @current_user ||= User.find_by_id(session[:user])
|
149
150
|
# end
|
151
|
+
#
|
152
|
+
# def logged_in?
|
153
|
+
# current_user != nil
|
154
|
+
# end
|
150
155
|
# end
|
156
|
+
#
|
157
|
+
# In a view:
|
158
|
+
# <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
|
151
159
|
def helper_method(*methods)
|
152
160
|
methods.flatten.each do |method|
|
153
161
|
master_helper_module.module_eval <<-end_eval
|
@@ -167,6 +175,15 @@ module ActionController #:nodoc:
|
|
167
175
|
attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
|
168
176
|
end
|
169
177
|
|
178
|
+
# Provides a proxy to access helpers methods from outside the view.
|
179
|
+
def helpers
|
180
|
+
unless @helper_proxy
|
181
|
+
@helper_proxy = ActionView::Base.new
|
182
|
+
@helper_proxy.extend master_helper_module
|
183
|
+
else
|
184
|
+
@helper_proxy
|
185
|
+
end
|
186
|
+
end
|
170
187
|
|
171
188
|
private
|
172
189
|
def default_helper_module!
|
@@ -70,7 +70,7 @@ module ActionController
|
|
70
70
|
#
|
71
71
|
# On shared hosts, Apache sometimes doesn't pass authentication headers to
|
72
72
|
# FCGI instances. If your environment matches this description and you cannot
|
73
|
-
# authenticate, try this rule in
|
73
|
+
# authenticate, try this rule in your Apache setup:
|
74
74
|
#
|
75
75
|
# RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
|
76
76
|
module Basic
|
@@ -55,7 +55,10 @@ module ActionController
|
|
55
55
|
# A running counter of the number of requests processed.
|
56
56
|
attr_accessor :request_count
|
57
57
|
|
58
|
-
|
58
|
+
class MultiPartNeededException < Exception
|
59
|
+
end
|
60
|
+
|
61
|
+
# Create and initialize a new Session instance.
|
59
62
|
def initialize
|
60
63
|
reset!
|
61
64
|
end
|
@@ -133,25 +136,25 @@ module ActionController
|
|
133
136
|
end
|
134
137
|
|
135
138
|
# Performs a GET request, following any subsequent redirect.
|
136
|
-
# See
|
139
|
+
# See +request_via_redirect+ for more information.
|
137
140
|
def get_via_redirect(path, parameters = nil, headers = nil)
|
138
141
|
request_via_redirect(:get, path, parameters, headers)
|
139
142
|
end
|
140
143
|
|
141
144
|
# Performs a POST request, following any subsequent redirect.
|
142
|
-
# See
|
145
|
+
# See +request_via_redirect+ for more information.
|
143
146
|
def post_via_redirect(path, parameters = nil, headers = nil)
|
144
147
|
request_via_redirect(:post, path, parameters, headers)
|
145
148
|
end
|
146
149
|
|
147
150
|
# Performs a PUT request, following any subsequent redirect.
|
148
|
-
# See
|
151
|
+
# See +request_via_redirect+ for more information.
|
149
152
|
def put_via_redirect(path, parameters = nil, headers = nil)
|
150
153
|
request_via_redirect(:put, path, parameters, headers)
|
151
154
|
end
|
152
155
|
|
153
156
|
# Performs a DELETE request, following any subsequent redirect.
|
154
|
-
# See
|
157
|
+
# See +request_via_redirect+ for more information.
|
155
158
|
def delete_via_redirect(path, parameters = nil, headers = nil)
|
156
159
|
request_via_redirect(:delete, path, parameters, headers)
|
157
160
|
end
|
@@ -163,12 +166,12 @@ module ActionController
|
|
163
166
|
|
164
167
|
# Performs a GET request with the given parameters. The parameters may
|
165
168
|
# be +nil+, a Hash, or a string that is appropriately encoded
|
166
|
-
# (application/x-www-form-urlencoded or multipart/form-data).
|
167
|
-
# should be a hash.
|
169
|
+
# (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
|
170
|
+
# The headers should be a hash. The keys will automatically be upcased, with the
|
168
171
|
# prefix 'HTTP_' added if needed.
|
169
172
|
#
|
170
|
-
# You can also perform POST, PUT, DELETE, and HEAD requests with
|
171
|
-
#
|
173
|
+
# You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
|
174
|
+
# +put+, +delete+, and +head+.
|
172
175
|
def get(path, parameters = nil, headers = nil)
|
173
176
|
process :get, path, parameters, headers
|
174
177
|
end
|
@@ -225,6 +228,8 @@ module ActionController
|
|
225
228
|
|
226
229
|
super
|
227
230
|
|
231
|
+
stdinput.set_encoding(Encoding::BINARY) if stdinput.respond_to?(:set_encoding)
|
232
|
+
stdinput.force_encoding(Encoding::BINARY) if stdinput.respond_to?(:force_encoding)
|
228
233
|
@stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '')
|
229
234
|
end
|
230
235
|
end
|
@@ -294,15 +299,19 @@ module ActionController
|
|
294
299
|
|
295
300
|
parse_result
|
296
301
|
return status
|
302
|
+
rescue MultiPartNeededException
|
303
|
+
boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
|
304
|
+
status = process(method, path, multipart_body(parameters, boundary), (headers || {}).merge({"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
|
305
|
+
return status
|
297
306
|
end
|
298
307
|
|
299
308
|
# Parses the result of the response and extracts the various values,
|
300
309
|
# like cookies, status, headers, etc.
|
301
310
|
def parse_result
|
302
|
-
|
311
|
+
response_headers, result_body = @result.split(/\r\n\r\n/, 2)
|
303
312
|
|
304
313
|
@headers = Hash.new { |h,k| h[k] = [] }
|
305
|
-
|
314
|
+
response_headers.to_s.each_line do |line|
|
306
315
|
key, value = line.strip.split(/:\s*/, 2)
|
307
316
|
@headers[key.downcase] << value
|
308
317
|
end
|
@@ -312,7 +321,7 @@ module ActionController
|
|
312
321
|
@cookies[name] = value
|
313
322
|
end
|
314
323
|
|
315
|
-
@status, @status_message = @headers["status"].first.split(/ /)
|
324
|
+
@status, @status_message = @headers["status"].first.to_s.split(/ /)
|
316
325
|
@status = @status.to_i
|
317
326
|
end
|
318
327
|
|
@@ -342,7 +351,9 @@ module ActionController
|
|
342
351
|
# Convert the given parameters to a request string. The parameters may
|
343
352
|
# be a string, +nil+, or a Hash.
|
344
353
|
def requestify(parameters, prefix=nil)
|
345
|
-
if
|
354
|
+
if TestUploadedFile === parameters
|
355
|
+
raise MultiPartNeededException
|
356
|
+
elsif Hash === parameters
|
346
357
|
return nil if parameters.empty?
|
347
358
|
parameters.map { |k,v| requestify(v, name_with_prefix(prefix, k)) }.join("&")
|
348
359
|
elsif Array === parameters
|
@@ -353,6 +364,47 @@ module ActionController
|
|
353
364
|
"#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}"
|
354
365
|
end
|
355
366
|
end
|
367
|
+
|
368
|
+
def multipart_requestify(params, first=true)
|
369
|
+
returning Hash.new do |p|
|
370
|
+
params.each do |key, value|
|
371
|
+
k = first ? CGI.escape(key.to_s) : "[#{CGI.escape(key.to_s)}]"
|
372
|
+
if Hash === value
|
373
|
+
multipart_requestify(value, false).each do |subkey, subvalue|
|
374
|
+
p[k + subkey] = subvalue
|
375
|
+
end
|
376
|
+
else
|
377
|
+
p[k] = value
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def multipart_body(params, boundary)
|
384
|
+
multipart_requestify(params).map do |key, value|
|
385
|
+
if value.respond_to?(:original_filename)
|
386
|
+
File.open(value.path) do |f|
|
387
|
+
f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
|
388
|
+
|
389
|
+
<<-EOF
|
390
|
+
--#{boundary}\r
|
391
|
+
Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
|
392
|
+
Content-Type: #{value.content_type}\r
|
393
|
+
Content-Length: #{File.stat(value.path).size}\r
|
394
|
+
\r
|
395
|
+
#{f.read}\r
|
396
|
+
EOF
|
397
|
+
end
|
398
|
+
else
|
399
|
+
<<-EOF
|
400
|
+
--#{boundary}\r
|
401
|
+
Content-Disposition: form-data; name="#{key}"\r
|
402
|
+
\r
|
403
|
+
#{value}\r
|
404
|
+
EOF
|
405
|
+
end
|
406
|
+
end.join("")+"--#{boundary}--\r"
|
407
|
+
end
|
356
408
|
end
|
357
409
|
|
358
410
|
# A module used to extend ActionController::Base, so that integration tests
|
@@ -65,15 +65,15 @@ module ActionController #:nodoc:
|
|
65
65
|
# == Automatic layout assignment
|
66
66
|
#
|
67
67
|
# If there is a template in <tt>app/views/layouts/</tt> with the same name as the current controller then it will be automatically
|
68
|
-
# set as that controller's layout unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named
|
68
|
+
# set as that controller's layout unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named
|
69
69
|
# <tt>app/views/layouts/weblog.erb</tt> or <tt>app/views/layouts/weblog.builder</tt> exists then it will be automatically set as
|
70
70
|
# the layout for your WeblogController. You can create a layout with the name <tt>application.erb</tt> or <tt>application.builder</tt>
|
71
|
-
# 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
|
71
|
+
# 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
|
72
72
|
# no layout explicitly assigned with the +layout+ method. Nested controllers use the same folder structure for automatic layout.
|
73
73
|
# assignment. So an Admin::WeblogController will look for a template named <tt>app/views/layouts/admin/weblog.erb</tt>.
|
74
74
|
# Setting a layout explicitly will always override the automatic behaviour for the controller where the layout is set.
|
75
75
|
# Explicitly setting the layout in a parent class, though, will not override the child class's layout assignment if the child
|
76
|
-
# class has a layout with the same name.
|
76
|
+
# class has a layout with the same name.
|
77
77
|
#
|
78
78
|
# == Inheritance for layouts
|
79
79
|
#
|
@@ -113,7 +113,7 @@ module ActionController #:nodoc:
|
|
113
113
|
# logged_in? ? "writer_layout" : "reader_layout"
|
114
114
|
# end
|
115
115
|
#
|
116
|
-
# Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing
|
116
|
+
# Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing
|
117
117
|
# is logged in or not.
|
118
118
|
#
|
119
119
|
# If you want to use an inline method, such as a proc, do something like this:
|
@@ -132,24 +132,24 @@ module ActionController #:nodoc:
|
|
132
132
|
# == Conditional layouts
|
133
133
|
#
|
134
134
|
# If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering
|
135
|
-
# a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The
|
135
|
+
# a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The
|
136
136
|
# <tt>:only</tt> and <tt>:except</tt> options can be passed to the layout call. For example:
|
137
137
|
#
|
138
138
|
# class WeblogController < ActionController::Base
|
139
139
|
# layout "weblog_standard", :except => :rss
|
140
|
-
#
|
140
|
+
#
|
141
141
|
# # ...
|
142
142
|
#
|
143
143
|
# end
|
144
144
|
#
|
145
|
-
# This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout
|
145
|
+
# This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout
|
146
146
|
# around the rendered view.
|
147
147
|
#
|
148
|
-
# Both the <tt>:only</tt> and <tt>:except</tt> condition can accept an arbitrary number of method references, so
|
148
|
+
# Both the <tt>:only</tt> and <tt>:except</tt> condition can accept an arbitrary number of method references, so
|
149
149
|
# #<tt>:except => [ :rss, :text_only ]</tt> is valid, as is <tt>:except => :rss</tt>.
|
150
150
|
#
|
151
151
|
# == Using a different layout in the action render call
|
152
|
-
#
|
152
|
+
#
|
153
153
|
# If most of your actions use the same layout, it makes perfect sense to define a controller-wide layout as described above.
|
154
154
|
# Sometimes you'll have exceptions where one action wants to use a different layout than the rest of the controller.
|
155
155
|
# You can do this by passing a <tt>:layout</tt> option to the <tt>render</tt> call. For example:
|
@@ -176,21 +176,19 @@ module ActionController #:nodoc:
|
|
176
176
|
def layout_conditions #:nodoc:
|
177
177
|
@layout_conditions ||= read_inheritable_attribute("layout_conditions")
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
def default_layout(format) #:nodoc:
|
181
|
-
layout = read_inheritable_attribute("layout")
|
181
|
+
layout = read_inheritable_attribute("layout")
|
182
182
|
return layout unless read_inheritable_attribute("auto_layout")
|
183
183
|
@default_layout ||= {}
|
184
184
|
@default_layout[format] ||= default_layout_with_format(format, layout)
|
185
185
|
@default_layout[format]
|
186
186
|
end
|
187
|
-
|
187
|
+
|
188
188
|
def layout_list #:nodoc:
|
189
|
-
view_paths.
|
190
|
-
Dir["#{path}/layouts/**/*"]
|
191
|
-
end.flatten
|
189
|
+
Array(view_paths).sum([]) { |path| Dir["#{path}/layouts/**/*"] }
|
192
190
|
end
|
193
|
-
|
191
|
+
|
194
192
|
private
|
195
193
|
def inherited_with_layout(child)
|
196
194
|
inherited_without_layout(child)
|
@@ -207,13 +205,7 @@ module ActionController #:nodoc:
|
|
207
205
|
def normalize_conditions(conditions)
|
208
206
|
conditions.inject({}) {|hash, (key, value)| hash.merge(key => [value].flatten.map {|action| action.to_s})}
|
209
207
|
end
|
210
|
-
|
211
|
-
def layout_directory_exists_cache
|
212
|
-
@@layout_directory_exists_cache ||= Hash.new do |h, dirname|
|
213
|
-
h[dirname] = File.directory? dirname
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
208
|
+
|
217
209
|
def default_layout_with_format(format, layout)
|
218
210
|
list = layout_list
|
219
211
|
if list.grep(%r{layouts/#{layout}\.#{format}(\.[a-z][0-9a-z]*)+$}).empty?
|
@@ -235,7 +227,7 @@ module ActionController #:nodoc:
|
|
235
227
|
when Symbol then send!(layout)
|
236
228
|
when Proc then layout.call(self)
|
237
229
|
end
|
238
|
-
|
230
|
+
|
239
231
|
# Explicitly passed layout names with slashes are looked up relative to the template root,
|
240
232
|
# but auto-discovered layouts derived from a nested controller will contain a slash, though be relative
|
241
233
|
# to the 'layouts' directory so we have to check the file system to infer which case the layout name came from.
|
@@ -249,16 +241,14 @@ module ActionController #:nodoc:
|
|
249
241
|
end
|
250
242
|
|
251
243
|
protected
|
252
|
-
def render_with_a_layout(options = nil, &block) #:nodoc:
|
244
|
+
def render_with_a_layout(options = nil, extra_options = {}, &block) #:nodoc:
|
253
245
|
template_with_options = options.is_a?(Hash)
|
254
|
-
|
255
|
-
if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options))
|
256
|
-
assert_existence_of_template_file(layout)
|
257
246
|
|
247
|
+
if (layout = pick_layout(template_with_options, options)) && apply_layout?(template_with_options, options)
|
258
248
|
options = options.merge :layout => false if template_with_options
|
259
249
|
logger.info("Rendering template within #{layout}") if logger
|
260
250
|
|
261
|
-
content_for_layout = render_with_no_layout(options, &block)
|
251
|
+
content_for_layout = render_with_no_layout(options, extra_options, &block)
|
262
252
|
erase_render_results
|
263
253
|
add_variables_to_assigns
|
264
254
|
@template.instance_variable_set("@content_for_layout", content_for_layout)
|
@@ -266,7 +256,7 @@ module ActionController #:nodoc:
|
|
266
256
|
status = template_with_options ? options[:status] : nil
|
267
257
|
render_for_text(@template.render_file(layout, true), status)
|
268
258
|
else
|
269
|
-
render_with_no_layout(options, &block)
|
259
|
+
render_with_no_layout(options, extra_options, &block)
|
270
260
|
end
|
271
261
|
end
|
272
262
|
|
@@ -278,7 +268,7 @@ module ActionController #:nodoc:
|
|
278
268
|
end
|
279
269
|
|
280
270
|
def candidate_for_layout?(options)
|
281
|
-
(options.has_key?(:layout) && options[:layout] != false) ||
|
271
|
+
(options.has_key?(:layout) && options[:layout] != false) ||
|
282
272
|
options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing).compact.empty? &&
|
283
273
|
!template_exempt_from_layout?(options[:template] || default_template_name(options[:action]))
|
284
274
|
end
|
@@ -304,7 +294,7 @@ module ActionController #:nodoc:
|
|
304
294
|
when only = conditions[:only]
|
305
295
|
only.include?(action_name)
|
306
296
|
when except = conditions[:except]
|
307
|
-
!except.include?(action_name)
|
297
|
+
!except.include?(action_name)
|
308
298
|
else
|
309
299
|
true
|
310
300
|
end
|
@@ -312,14 +302,9 @@ module ActionController #:nodoc:
|
|
312
302
|
true
|
313
303
|
end
|
314
304
|
end
|
315
|
-
|
316
|
-
# Does a layout directory for this class exist?
|
317
|
-
# we cache this info in a class level hash
|
305
|
+
|
318
306
|
def layout_directory?(layout_name)
|
319
|
-
|
320
|
-
next unless template_path = Dir[File.join(path, 'layouts', layout_name) + ".*"].first
|
321
|
-
self.class.send!(:layout_directory_exists_cache)[File.dirname(template_path)]
|
322
|
-
end
|
307
|
+
@template.finder.find_template_extension_from_handler(File.join('layouts', layout_name))
|
323
308
|
end
|
324
309
|
end
|
325
310
|
end
|