actionpack 3.0.20 → 3.1.0.beta1
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 +88 -142
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +24 -19
- data/lib/abstract_controller/callbacks.rb +19 -19
- data/lib/abstract_controller/helpers.rb +11 -13
- data/lib/abstract_controller/layouts.rb +4 -5
- data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
- data/lib/abstract_controller/rendering.rb +34 -31
- data/lib/abstract_controller/url_for.rb +27 -0
- data/lib/abstract_controller/view_paths.rb +31 -6
- data/lib/action_controller.rb +5 -3
- data/lib/action_controller/base.rb +15 -16
- data/lib/action_controller/caching.rb +2 -2
- data/lib/action_controller/caching/actions.rb +11 -12
- data/lib/action_controller/caching/fragments.rb +41 -19
- data/lib/action_controller/caching/pages.rb +3 -9
- data/lib/action_controller/caching/sweeping.rb +0 -1
- data/lib/action_controller/deprecated.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +78 -20
- data/lib/action_controller/metal/compatibility.rb +0 -9
- data/lib/action_controller/metal/conditional_get.rb +9 -9
- data/lib/action_controller/metal/data_streaming.rb +145 -0
- data/lib/action_controller/metal/force_ssl.rb +35 -0
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +37 -44
- data/lib/action_controller/metal/hide_actions.rb +2 -3
- data/lib/action_controller/metal/http_authentication.rb +41 -38
- data/lib/action_controller/metal/implicit_render.rb +13 -13
- data/lib/action_controller/metal/instrumentation.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +25 -19
- data/lib/action_controller/metal/params_wrapper.rb +224 -0
- data/lib/action_controller/metal/redirecting.rb +6 -2
- data/lib/action_controller/metal/renderers.rb +50 -36
- data/lib/action_controller/metal/rendering.rb +34 -25
- data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
- data/lib/action_controller/metal/responder.rb +47 -12
- data/lib/action_controller/metal/streaming.rb +244 -138
- data/lib/action_controller/metal/testing.rb +0 -9
- data/lib/action_controller/metal/url_for.rb +12 -14
- data/lib/action_controller/railtie.rb +19 -37
- data/lib/action_controller/railties/paths.rb +24 -0
- data/lib/action_controller/record_identifier.rb +4 -10
- data/lib/action_controller/test_case.rb +36 -19
- data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_dispatch/http/cache.rb +5 -32
- data/lib/action_dispatch/http/filter_parameters.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
- data/lib/action_dispatch/http/mime_type.rb +45 -5
- data/lib/action_dispatch/http/rack_cache.rb +58 -0
- data/lib/action_dispatch/http/request.rb +27 -41
- data/lib/action_dispatch/http/response.rb +56 -54
- data/lib/action_dispatch/http/upload.rb +1 -11
- data/lib/action_dispatch/http/url.rb +102 -42
- data/lib/action_dispatch/middleware/callbacks.rb +8 -25
- data/lib/action_dispatch/middleware/closed_error.rb +7 -0
- data/lib/action_dispatch/middleware/cookies.rb +37 -15
- data/lib/action_dispatch/middleware/flash.rb +80 -11
- data/lib/action_dispatch/middleware/params_parser.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
- data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
- data/lib/action_dispatch/middleware/stack.rb +50 -17
- data/lib/action_dispatch/middleware/static.rb +41 -29
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/routing.rb +13 -1
- data/lib/action_dispatch/routing/mapper.rb +345 -227
- data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
- data/lib/action_dispatch/routing/redirection.rb +110 -0
- data/lib/action_dispatch/routing/route.rb +15 -13
- data/lib/action_dispatch/routing/route_set.rb +116 -90
- data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
- data/lib/action_dispatch/routing/url_for.rb +25 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -10
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
- data/lib/action_dispatch/testing/integration.rb +37 -28
- data/lib/action_dispatch/testing/performance_test.rb +1 -3
- data/lib/action_dispatch/testing/test_process.rb +1 -1
- data/lib/action_dispatch/testing/test_request.rb +9 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -111
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +39 -24
- data/lib/action_view/base.rb +61 -86
- data/lib/action_view/buffers.rb +43 -0
- data/lib/action_view/context.rb +21 -24
- data/lib/action_view/flows.rb +79 -0
- data/lib/action_view/helpers.rb +8 -6
- data/lib/action_view/helpers/active_model_helper.rb +0 -23
- data/lib/action_view/helpers/asset_paths.rb +79 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +11 -19
- data/lib/action_view/helpers/capture_helper.rb +19 -8
- data/lib/action_view/helpers/controller_helper.rb +21 -0
- data/lib/action_view/helpers/csrf_helper.rb +22 -4
- data/lib/action_view/helpers/date_helper.rb +36 -22
- data/lib/action_view/helpers/form_helper.rb +199 -113
- data/lib/action_view/helpers/form_options_helper.rb +10 -11
- data/lib/action_view/helpers/form_tag_helper.rb +94 -22
- data/lib/action_view/helpers/javascript_helper.rb +24 -107
- data/lib/action_view/helpers/number_helper.rb +36 -33
- data/lib/action_view/helpers/output_safety_helper.rb +38 -0
- data/lib/action_view/helpers/record_tag_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +90 -0
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/sprockets_helper.rb +69 -0
- data/lib/action_view/helpers/tag_helper.rb +34 -12
- data/lib/action_view/helpers/text_helper.rb +30 -145
- data/lib/action_view/helpers/translation_helper.rb +10 -17
- data/lib/action_view/helpers/url_helper.rb +70 -67
- data/lib/action_view/locale/en.yml +1 -1
- data/lib/action_view/lookup_context.rb +36 -14
- data/lib/action_view/{paths.rb → path_set.rb} +9 -8
- data/lib/action_view/railtie.rb +12 -4
- data/lib/action_view/renderer/abstract_renderer.rb +36 -0
- data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
- data/lib/action_view/renderer/renderer.rb +54 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
- data/lib/action_view/renderer/template_renderer.rb +74 -0
- data/lib/action_view/template.rb +91 -54
- data/lib/action_view/template/error.rb +11 -8
- data/lib/action_view/template/handler.rb +9 -1
- data/lib/action_view/template/handlers.rb +9 -9
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb.rb +21 -41
- data/lib/action_view/template/resolver.rb +171 -57
- data/lib/action_view/template/text.rb +0 -4
- data/lib/action_view/test_case.rb +32 -16
- data/lib/action_view/testing/resolvers.rb +16 -10
- data/lib/sprockets/railtie.rb +100 -0
- metadata +162 -140
- checksums.yaml +0 -7
- data/lib/action_controller/deprecated/base.rb +0 -143
- data/lib/action_controller/deprecated/dispatcher.rb +0 -28
- data/lib/action_controller/deprecated/url_writer.rb +0 -14
- data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
- data/lib/action_view/helpers/prototype_helper.rb +0 -851
- data/lib/action_view/helpers/raw_output_helper.rb +0 -18
- data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
- data/lib/action_view/render/layouts.rb +0 -83
- data/lib/action_view/render/rendering.rb +0 -67
- data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -3,7 +3,7 @@ require 'uri'
|
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
module ActionController #:nodoc:
|
6
|
-
# Caching is a cheap way of speeding up slow applications by keeping the result of
|
6
|
+
# \Caching is a cheap way of speeding up slow applications by keeping the result of
|
7
7
|
# calculations, renderings, and database calls around for subsequent requests.
|
8
8
|
# Action Controller affords you three approaches in varying levels of granularity:
|
9
9
|
# Page, Action, Fragment.
|
@@ -14,7 +14,7 @@ module ActionController #:nodoc:
|
|
14
14
|
# Note: To turn off all caching and sweeping, set
|
15
15
|
# config.action_controller.perform_caching = false.
|
16
16
|
#
|
17
|
-
# == Caching stores
|
17
|
+
# == \Caching stores
|
18
18
|
#
|
19
19
|
# All the caching stores from ActiveSupport::Cache are available to be used as backends
|
20
20
|
# for Action Controller caching. This setting only affects action and fragment caching
|
@@ -31,8 +31,8 @@ module ActionController #:nodoc:
|
|
31
31
|
# the subdomain-as-account-key pattern.
|
32
32
|
#
|
33
33
|
# Different representations of the same resource, e.g.
|
34
|
-
# <tt>http://david.
|
35
|
-
# <tt>http://david.
|
34
|
+
# <tt>http://david.example.com/lists</tt> and
|
35
|
+
# <tt>http://david.example.com/lists.xml</tt>
|
36
36
|
# are treated like separate requests and so are cached separately.
|
37
37
|
# Keep in mind when expiring an action cache that
|
38
38
|
# <tt>:action => 'lists'</tt> is not the same as
|
@@ -56,19 +56,18 @@ module ActionController #:nodoc:
|
|
56
56
|
#
|
57
57
|
# caches_page :public
|
58
58
|
#
|
59
|
-
# caches_action :index, :if => proc do
|
60
|
-
# !
|
59
|
+
# caches_action :index, :if => proc do
|
60
|
+
# !request.format.json? # cache if is not a JSON request
|
61
61
|
# end
|
62
62
|
#
|
63
63
|
# caches_action :show, :cache_path => { :project => 1 },
|
64
64
|
# :expires_in => 1.hour
|
65
65
|
#
|
66
|
-
# caches_action :feed, :cache_path => proc do
|
67
|
-
# if
|
68
|
-
#
|
69
|
-
# c.params[:user_id], c.params[:id])
|
66
|
+
# caches_action :feed, :cache_path => proc do
|
67
|
+
# if params[:user_id]
|
68
|
+
# user_list_url(params[:user_id, params[:id])
|
70
69
|
# else
|
71
|
-
#
|
70
|
+
# list_url(params[:id])
|
72
71
|
# end
|
73
72
|
# end
|
74
73
|
# end
|
@@ -80,7 +79,7 @@ module ActionController #:nodoc:
|
|
80
79
|
# header the Content-Type of the cached response could be wrong because
|
81
80
|
# no information about the MIME type is stored in the cache key. So, if
|
82
81
|
# you first ask for MIME type M in the Accept header, a cache entry is
|
83
|
-
# created, and then perform a second
|
82
|
+
# created, and then perform a second request to the same resource asking
|
84
83
|
# for a different MIME type, you'd get the content cached for M.
|
85
84
|
#
|
86
85
|
# The <tt>:format</tt> parameter is taken into account though. The safest
|
@@ -160,7 +159,7 @@ module ActionController #:nodoc:
|
|
160
159
|
attr_reader :path, :extension
|
161
160
|
|
162
161
|
# If +infer_extension+ is true, the cache path extension is looked up from the request's
|
163
|
-
# path
|
162
|
+
# path and format. This is desirable when reading and writing the cache, but not when
|
164
163
|
# expiring the cache - expire_action should expire the same files regardless of the
|
165
164
|
# request format.
|
166
165
|
def initialize(controller, options = {}, infer_extension = true)
|
@@ -177,7 +176,7 @@ module ActionController #:nodoc:
|
|
177
176
|
def normalize!(path)
|
178
177
|
path << 'index' if path[-1] == ?/
|
179
178
|
path << ".#{extension}" if extension and !path.ends_with?(extension)
|
180
|
-
URI.unescape(path)
|
179
|
+
URI.parser.unescape(path)
|
181
180
|
end
|
182
181
|
end
|
183
182
|
end
|
@@ -1,52 +1,72 @@
|
|
1
1
|
module ActionController #:nodoc:
|
2
2
|
module Caching
|
3
|
-
# Fragment caching is used for caching various blocks within
|
4
|
-
#
|
5
|
-
#
|
3
|
+
# Fragment caching is used for caching various blocks within
|
4
|
+
# views without caching the entire action as a whole. This is
|
5
|
+
# useful when certain elements of an action change frequently or
|
6
|
+
# depend on complicated state while other parts rarely change or
|
7
|
+
# can be shared amongst multiple parties. The caching is done using
|
8
|
+
# the <tt>cache</tt> helper available in the Action View. A
|
9
|
+
# template with fragment caching might look like:
|
6
10
|
#
|
7
11
|
# <b>Hello <%= @name %></b>
|
12
|
+
#
|
8
13
|
# <% cache do %>
|
9
14
|
# All the topics in the system:
|
10
15
|
# <%= render :partial => "topic", :collection => Topic.find(:all) %>
|
11
16
|
# <% end %>
|
12
17
|
#
|
13
|
-
# This cache will bind
|
14
|
-
#
|
18
|
+
# This cache will bind the name of the action that called it, so if
|
19
|
+
# this code was part of the view for the topics/list action, you
|
20
|
+
# would be able to invalidate it using:
|
21
|
+
#
|
22
|
+
# expire_fragment(:controller => "topics", :action => "list")
|
15
23
|
#
|
16
|
-
# This default behavior is
|
17
|
-
#
|
24
|
+
# This default behavior is limited if you need to cache multiple
|
25
|
+
# fragments per action or if the action itself is cached using
|
26
|
+
# <tt>caches_action</tt>. To remedy this, there is an option to
|
27
|
+
# qualify the name of the cached fragment by using the
|
28
|
+
# <tt>:action_suffix</tt> option:
|
18
29
|
#
|
19
30
|
# <% cache(:action => "list", :action_suffix => "all_topics") do %>
|
20
31
|
#
|
21
|
-
# That would result in a name such as
|
22
|
-
#
|
23
|
-
# cache
|
32
|
+
# That would result in a name such as
|
33
|
+
# <tt>/topics/list/all_topics</tt>, avoiding conflicts with the
|
34
|
+
# action cache and with any fragments that use a different suffix.
|
35
|
+
# Note that the URL doesn't have to really exist or be callable
|
36
|
+
# - the url_for system is just used to generate unique cache names
|
37
|
+
# that we can refer to when we need to expire the cache.
|
24
38
|
#
|
25
39
|
# The expiration call for this example is:
|
26
40
|
#
|
27
|
-
# expire_fragment(:controller => "topics",
|
41
|
+
# expire_fragment(:controller => "topics",
|
42
|
+
# :action => "list",
|
43
|
+
# :action_suffix => "all_topics")
|
28
44
|
module Fragments
|
29
|
-
# Given a key (as described in <tt>expire_fragment</tt>), returns
|
30
|
-
#
|
31
|
-
#
|
45
|
+
# Given a key (as described in <tt>expire_fragment</tt>), returns
|
46
|
+
# a key suitable for use in reading, writing, or expiring a
|
47
|
+
# cached fragment. If the key is a hash, the generated key is the
|
48
|
+
# return value of url_for on that hash (without the protocol).
|
49
|
+
# All keys are prefixed with <tt>views/</tt> and uses
|
32
50
|
# ActiveSupport::Cache.expand_cache_key for the expansion.
|
33
51
|
def fragment_cache_key(key)
|
34
52
|
ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
|
35
53
|
end
|
36
54
|
|
37
|
-
# Writes <tt>content</tt> to the location signified by
|
55
|
+
# Writes <tt>content</tt> to the location signified by
|
56
|
+
# <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats).
|
38
57
|
def write_fragment(key, content, options = nil)
|
39
58
|
return content unless cache_configured?
|
40
59
|
|
41
60
|
key = fragment_cache_key(key)
|
42
61
|
instrument_fragment_cache :write_fragment, key do
|
43
|
-
content = content.
|
62
|
+
content = content.to_str
|
44
63
|
cache_store.write(key, content, options)
|
45
64
|
end
|
46
65
|
content
|
47
66
|
end
|
48
67
|
|
49
|
-
# Reads a cached fragment from the location signified by <tt>key</tt>
|
68
|
+
# Reads a cached fragment from the location signified by <tt>key</tt>
|
69
|
+
# (see <tt>expire_fragment</tt> for acceptable formats).
|
50
70
|
def read_fragment(key, options = nil)
|
51
71
|
return unless cache_configured?
|
52
72
|
|
@@ -57,7 +77,8 @@ module ActionController #:nodoc:
|
|
57
77
|
end
|
58
78
|
end
|
59
79
|
|
60
|
-
# Check if a cached fragment from the location signified by
|
80
|
+
# Check if a cached fragment from the location signified by
|
81
|
+
# <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
|
61
82
|
def fragment_exist?(key, options = nil)
|
62
83
|
return unless cache_configured?
|
63
84
|
key = fragment_cache_key(key)
|
@@ -70,8 +91,9 @@ module ActionController #:nodoc:
|
|
70
91
|
# Removes fragments from the cache.
|
71
92
|
#
|
72
93
|
# +key+ can take one of three forms:
|
94
|
+
#
|
73
95
|
# * String - This would normally take the form of a path, like
|
74
|
-
# <tt>
|
96
|
+
# <tt>pages/45/notes</tt>.
|
75
97
|
# * Hash - Treated as an implicit call to +url_for+, like
|
76
98
|
# <tt>{:controller => "pages", :action => "notes", :id => 45}</tt>
|
77
99
|
# * Regexp - Will remove any fragment that matches, so
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
require 'uri'
|
3
2
|
require 'active_support/core_ext/class/attribute_accessors'
|
4
3
|
|
5
4
|
module ActionController #:nodoc:
|
@@ -99,7 +98,7 @@ module ActionController #:nodoc:
|
|
99
98
|
|
100
99
|
private
|
101
100
|
def page_cache_file(path, extension)
|
102
|
-
name = (path.empty? || path == "/") ? "/index" : URI.unescape(path.chomp('/'))
|
101
|
+
name = (path.empty? || path == "/") ? "/index" : URI.parser.unescape(path.chomp('/'))
|
103
102
|
unless (name.split('/').last || name).include? '.'
|
104
103
|
name << (extension || self.page_cache_extension)
|
105
104
|
end
|
@@ -107,7 +106,7 @@ module ActionController #:nodoc:
|
|
107
106
|
end
|
108
107
|
|
109
108
|
def page_cache_path(path, extension = nil)
|
110
|
-
page_cache_directory + page_cache_file(path, extension)
|
109
|
+
page_cache_directory.to_s + page_cache_file(path, extension)
|
111
110
|
end
|
112
111
|
|
113
112
|
def instrument_page_cache(name, path)
|
@@ -137,7 +136,7 @@ module ActionController #:nodoc:
|
|
137
136
|
# If no options are provided, the requested url is used. Example:
|
138
137
|
# cache_page "I'm the cached content", :controller => "lists", :action => "show"
|
139
138
|
def cache_page(content = nil, options = nil)
|
140
|
-
return unless self.class.perform_caching && caching_allowed
|
139
|
+
return unless self.class.perform_caching && caching_allowed?
|
141
140
|
|
142
141
|
path = case options
|
143
142
|
when Hash
|
@@ -148,7 +147,6 @@ module ActionController #:nodoc:
|
|
148
147
|
request.path
|
149
148
|
end
|
150
149
|
|
151
|
-
|
152
150
|
if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
|
153
151
|
extension = ".#{type_symbol}"
|
154
152
|
end
|
@@ -156,10 +154,6 @@ module ActionController #:nodoc:
|
|
156
154
|
self.class.cache_page(content || response.body, path, extension)
|
157
155
|
end
|
158
156
|
|
159
|
-
private
|
160
|
-
def caching_allowed
|
161
|
-
request.get? && response.status.to_i == 200
|
162
|
-
end
|
163
157
|
end
|
164
158
|
end
|
165
159
|
end
|
@@ -1,3 +1,3 @@
|
|
1
1
|
ActionController::AbstractRequest = ActionController::Request = ActionDispatch::Request
|
2
2
|
ActionController::AbstractResponse = ActionController::Response = ActionDispatch::Response
|
3
|
-
ActionController::Routing = ActionDispatch::Routing
|
3
|
+
ActionController::Routing = ActionDispatch::Routing
|
@@ -46,7 +46,7 @@ module ActionController
|
|
46
46
|
def #{method}(event)
|
47
47
|
key_or_path = event.payload[:key] || event.payload[:path]
|
48
48
|
human_name = #{method.to_s.humanize.inspect}
|
49
|
-
info("\#{human_name} \#{key_or_path} (%.1fms)" % event.duration)
|
49
|
+
info("\#{human_name} \#{key_or_path} \#{"(%.1fms)" % event.duration}")
|
50
50
|
end
|
51
51
|
METHOD
|
52
52
|
end
|
@@ -36,35 +36,88 @@ module ActionController
|
|
36
36
|
action = action.to_s
|
37
37
|
raise "MiddlewareStack#build requires an app" unless app
|
38
38
|
|
39
|
-
reverse.inject(app) do |a, middleware|
|
39
|
+
middlewares.reverse.inject(app) do |a, middleware|
|
40
40
|
middleware.valid?(action) ?
|
41
41
|
middleware.build(a) : a
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
# ActionController::Metal
|
46
|
+
# <tt>ActionController::Metal</tt> is the simplest possible controller, providing a
|
47
|
+
# valid Rack interface without the additional niceties provided by
|
48
|
+
# <tt>ActionController::Base</tt>.
|
49
|
+
#
|
50
|
+
# A sample metal controller might look like this:
|
51
|
+
#
|
52
|
+
# class HelloController < ActionController::Metal
|
53
|
+
# def index
|
54
|
+
# self.response_body = "Hello World!"
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# And then to route requests to your metal controller, you would add
|
59
|
+
# something like this to <tt>config/routes.rb</tt>:
|
60
|
+
#
|
61
|
+
# match 'hello', :to => HelloController.action(:index)
|
62
|
+
#
|
63
|
+
# The +action+ method returns a valid Rack application for the \Rails
|
64
|
+
# router to dispatch to.
|
65
|
+
#
|
66
|
+
# == Rendering Helpers
|
67
|
+
#
|
68
|
+
# <tt>ActionController::Metal</tt> by default provides no utilities for rendering
|
69
|
+
# views, partials, or other responses aside from explicitly calling of
|
70
|
+
# <tt>response_body=</tt>, <tt>content_type=</tt>, and <tt>status=</tt>. To
|
71
|
+
# add the render helpers you're used to having in a normal controller, you
|
72
|
+
# can do the following:
|
73
|
+
#
|
74
|
+
# class HelloController < ActionController::Metal
|
75
|
+
# include ActionController::Rendering
|
76
|
+
# append_view_path "#{Rails.root}/app/views"
|
77
|
+
#
|
78
|
+
# def index
|
79
|
+
# render "hello/index"
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# == Redirection Helpers
|
84
|
+
#
|
85
|
+
# To add redirection helpers to your metal controller, do the following:
|
86
|
+
#
|
87
|
+
# class HelloController < ActionController::Metal
|
88
|
+
# include ActionController::Redirecting
|
89
|
+
# include Rails.application.routes.url_helpers
|
90
|
+
#
|
91
|
+
# def index
|
92
|
+
# redirect_to root_url
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# == Other Helpers
|
97
|
+
#
|
98
|
+
# You can refer to the modules included in <tt>ActionController::Base</tt> to see
|
99
|
+
# other features you can bring into your metal controller.
|
47
100
|
#
|
48
|
-
# In AbstractController, dispatching is triggered directly by calling #process on a new controller.
|
49
|
-
# ActionController::Metal provides an #action method that returns a valid Rack application for a
|
50
|
-
# given action. Other rack builders, such as Rack::Builder, Rack::URLMap, and the Rails router,
|
51
|
-
# can dispatch directly to the action returned by FooController.action(:index).
|
52
101
|
class Metal < AbstractController::Base
|
53
102
|
abstract!
|
54
103
|
|
55
|
-
|
104
|
+
attr_internal_writer :env
|
105
|
+
|
106
|
+
def env
|
107
|
+
@_env ||= {}
|
108
|
+
end
|
56
109
|
|
57
110
|
# Returns the last part of the controller's name, underscored, without the ending
|
58
|
-
#
|
59
|
-
#
|
111
|
+
# <tt>Controller</tt>. For instance, PostsController returns <tt>posts</tt>.
|
112
|
+
# Namespaces are left out, so Admin::PostsController returns <tt>posts</tt> as well.
|
60
113
|
#
|
61
114
|
# ==== Returns
|
62
|
-
#
|
115
|
+
# * <tt>string</tt>
|
63
116
|
def self.controller_name
|
64
117
|
@controller_name ||= self.name.demodulize.sub(/Controller$/, '').underscore
|
65
118
|
end
|
66
119
|
|
67
|
-
# Delegates to the class'
|
120
|
+
# Delegates to the class' <tt>controller_name</tt>
|
68
121
|
def controller_name
|
69
122
|
self.class.controller_name
|
70
123
|
end
|
@@ -78,9 +131,12 @@ module ActionController
|
|
78
131
|
attr_internal :headers, :response, :request
|
79
132
|
delegate :session, :to => "@_request"
|
80
133
|
|
81
|
-
def initialize
|
134
|
+
def initialize
|
82
135
|
@_headers = {"Content-Type" => "text/html"}
|
83
136
|
@_status = 200
|
137
|
+
@_request = nil
|
138
|
+
@_response = nil
|
139
|
+
@_routes = nil
|
84
140
|
super
|
85
141
|
end
|
86
142
|
|
@@ -126,12 +182,11 @@ module ActionController
|
|
126
182
|
end
|
127
183
|
|
128
184
|
def response_body=(val)
|
129
|
-
body = val.respond_to?(:each) ? val : [val]
|
185
|
+
body = val.nil? ? nil : (val.respond_to?(:each) ? val : [val])
|
130
186
|
super body
|
131
187
|
end
|
132
188
|
|
133
|
-
|
134
|
-
def dispatch(name, request)
|
189
|
+
def dispatch(name, request) #:nodoc:
|
135
190
|
@_request = request
|
136
191
|
@_env = request.env
|
137
192
|
@_env['action_controller.instance'] = self
|
@@ -139,27 +194,30 @@ module ActionController
|
|
139
194
|
to_a
|
140
195
|
end
|
141
196
|
|
142
|
-
|
143
|
-
def to_a
|
197
|
+
def to_a #:nodoc:
|
144
198
|
response ? response.to_a : [status, headers, response_body]
|
145
199
|
end
|
146
200
|
|
147
201
|
class_attribute :middleware_stack
|
148
202
|
self.middleware_stack = ActionController::MiddlewareStack.new
|
149
203
|
|
150
|
-
def self.inherited(base)
|
204
|
+
def self.inherited(base) #nodoc:
|
151
205
|
base.middleware_stack = self.middleware_stack.dup
|
152
206
|
super
|
153
207
|
end
|
154
208
|
|
209
|
+
# Adds given middleware class and its args to bottom of middleware_stack
|
155
210
|
def self.use(*args, &block)
|
156
211
|
middleware_stack.use(*args, &block)
|
157
212
|
end
|
158
213
|
|
214
|
+
# Alias for middleware_stack
|
159
215
|
def self.middleware
|
160
216
|
middleware_stack
|
161
217
|
end
|
162
218
|
|
219
|
+
# Makes the controller a rack endpoint that points to the action in
|
220
|
+
# the given env's action_dispatch.request.path_parameters key.
|
163
221
|
def self.call(env)
|
164
222
|
action(env['action_dispatch.request.path_parameters'][:action]).call(env)
|
165
223
|
end
|
@@ -169,10 +227,10 @@ module ActionController
|
|
169
227
|
# for the same action.
|
170
228
|
#
|
171
229
|
# ==== Parameters
|
172
|
-
# action
|
230
|
+
# * <tt>action</tt> - An action name
|
173
231
|
#
|
174
232
|
# ==== Returns
|
175
|
-
#
|
233
|
+
# * <tt>proc</tt> - A rack application
|
176
234
|
def self.action(name, klass = ActionDispatch::Request)
|
177
235
|
middleware_stack.build(name.to_s) do |env|
|
178
236
|
new.dispatch(name, klass.new(env))
|
@@ -5,9 +5,6 @@ module ActionController
|
|
5
5
|
class ::ActionController::ActionControllerError < StandardError #:nodoc:
|
6
6
|
end
|
7
7
|
|
8
|
-
module ClassMethods
|
9
|
-
end
|
10
|
-
|
11
8
|
# Temporary hax
|
12
9
|
included do
|
13
10
|
::ActionController::UnknownAction = ::AbstractController::ActionNotFound
|
@@ -39,12 +36,6 @@ module ActionController
|
|
39
36
|
def assign_shortcuts(*) end
|
40
37
|
|
41
38
|
def _normalize_options(options)
|
42
|
-
if options[:action] && options[:action].to_s.include?(?/)
|
43
|
-
ActiveSupport::Deprecation.warn "Giving a path to render :action is deprecated. " <<
|
44
|
-
"Please use render :template instead", caller
|
45
|
-
options[:template] = options.delete(:action)
|
46
|
-
end
|
47
|
-
|
48
39
|
options[:text] = nil if options.delete(:nothing) == true
|
49
40
|
options[:text] = " " if options.key?(:text) && options[:text].nil?
|
50
41
|
super
|