actionpack 3.2.22.5 → 4.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +641 -418
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -288
- data/lib/abstract_controller.rb +1 -8
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +39 -37
- data/lib/abstract_controller/callbacks.rb +101 -82
- data/lib/abstract_controller/collector.rb +7 -3
- data/lib/abstract_controller/helpers.rb +23 -11
- data/lib/abstract_controller/layouts.rb +68 -73
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/rendering.rb +22 -13
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +6 -6
- data/lib/abstract_controller/view_paths.rb +1 -1
- data/lib/action_controller.rb +15 -6
- data/lib/action_controller/base.rb +46 -22
- data/lib/action_controller/caching.rb +46 -33
- data/lib/action_controller/caching/fragments.rb +23 -53
- data/lib/action_controller/deprecated.rb +5 -1
- data/lib/action_controller/deprecated/integration_test.rb +3 -0
- data/lib/action_controller/log_subscriber.rb +11 -8
- data/lib/action_controller/metal.rb +16 -30
- data/lib/action_controller/metal/conditional_get.rb +76 -32
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +24 -9
- data/lib/action_controller/metal/force_ssl.rb +32 -9
- data/lib/action_controller/metal/head.rb +25 -4
- data/lib/action_controller/metal/helpers.rb +6 -9
- data/lib/action_controller/metal/hide_actions.rb +1 -2
- data/lib/action_controller/metal/http_authentication.rb +105 -87
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +2 -1
- data/lib/action_controller/metal/live.rb +141 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -47
- data/lib/action_controller/metal/params_wrapper.rb +112 -74
- data/lib/action_controller/metal/rack_delegation.rb +9 -3
- data/lib/action_controller/metal/redirecting.rb +15 -20
- data/lib/action_controller/metal/renderers.rb +11 -9
- data/lib/action_controller/metal/rendering.rb +8 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
- data/lib/action_controller/metal/responder.rb +20 -19
- data/lib/action_controller/metal/streaming.rb +12 -18
- data/lib/action_controller/metal/strong_parameters.rb +516 -0
- data/lib/action_controller/metal/testing.rb +13 -18
- data/lib/action_controller/metal/url_for.rb +27 -25
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +33 -17
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/record_identifier.rb +18 -72
- data/lib/action_controller/test_case.rb +215 -123
- data/lib/action_controller/vendor/html-scanner.rb +4 -19
- data/lib/action_dispatch.rb +27 -19
- data/lib/action_dispatch/http/cache.rb +63 -11
- data/lib/action_dispatch/http/filter_parameters.rb +18 -8
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +27 -19
- data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
- data/lib/action_dispatch/http/mime_type.rb +145 -113
- data/lib/action_dispatch/http/mime_types.rb +1 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +12 -5
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +49 -18
- data/lib/action_dispatch/http/response.rb +129 -35
- data/lib/action_dispatch/http/upload.rb +60 -17
- data/lib/action_dispatch/http/url.rb +53 -31
- data/lib/action_dispatch/journey.rb +5 -0
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +146 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
- data/lib/action_dispatch/journey/nodes/node.rb +124 -0
- data/lib/action_dispatch/journey/parser.rb +206 -0
- data/lib/action_dispatch/journey/parser.y +47 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +196 -0
- data/lib/action_dispatch/journey/route.rb +116 -0
- data/lib/action_dispatch/journey/router.rb +164 -0
- data/lib/action_dispatch/journey/router/strexp.rb +24 -0
- data/lib/action_dispatch/journey/router/utils.rb +54 -0
- data/lib/action_dispatch/journey/routes.rb +75 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +189 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/middleware/callbacks.rb +9 -4
- data/lib/action_dispatch/middleware/cookies.rb +168 -57
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
- data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
- data/lib/action_dispatch/middleware/flash.rb +58 -58
- data/lib/action_dispatch/middleware/params_parser.rb +14 -29
- data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
- data/lib/action_dispatch/middleware/reloader.rb +6 -6
- data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
- data/lib/action_dispatch/middleware/request_id.rb +2 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
- data/lib/action_dispatch/middleware/ssl.rb +70 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +5 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
- data/lib/action_dispatch/railtie.rb +16 -6
- data/lib/action_dispatch/request/session.rb +181 -0
- data/lib/action_dispatch/routing.rb +41 -40
- data/lib/action_dispatch/routing/inspector.rb +240 -0
- data/lib/action_dispatch/routing/mapper.rb +501 -273
- data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
- data/lib/action_dispatch/routing/redirection.rb +46 -29
- data/lib/action_dispatch/routing/route_set.rb +203 -164
- data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
- data/lib/action_dispatch/routing/url_for.rb +48 -33
- data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
- data/lib/action_dispatch/testing/assertions/response.rb +32 -40
- data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
- data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
- data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
- data/lib/action_dispatch/testing/integration.rb +41 -22
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +7 -3
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +4 -4
- data/lib/action_view.rb +17 -8
- data/lib/action_view/base.rb +15 -34
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +4 -4
- data/lib/action_view/dependency_tracker.rb +91 -0
- data/lib/action_view/digestor.rb +85 -0
- data/lib/action_view/flows.rb +1 -4
- data/lib/action_view/helpers.rb +2 -4
- data/lib/action_view/helpers/active_model_helper.rb +3 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
- data/lib/action_view/helpers/asset_url_helper.rb +354 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
- data/lib/action_view/helpers/cache_helper.rb +150 -18
- data/lib/action_view/helpers/capture_helper.rb +42 -29
- data/lib/action_view/helpers/csrf_helper.rb +0 -2
- data/lib/action_view/helpers/date_helper.rb +268 -247
- data/lib/action_view/helpers/debug_helper.rb +10 -11
- data/lib/action_view/helpers/form_helper.rb +904 -547
- data/lib/action_view/helpers/form_options_helper.rb +341 -166
- data/lib/action_view/helpers/form_tag_helper.rb +188 -88
- data/lib/action_view/helpers/javascript_helper.rb +23 -16
- data/lib/action_view/helpers/number_helper.rb +148 -354
- data/lib/action_view/helpers/output_safety_helper.rb +3 -3
- data/lib/action_view/helpers/record_tag_helper.rb +17 -22
- data/lib/action_view/helpers/rendering_helper.rb +2 -4
- data/lib/action_view/helpers/sanitize_helper.rb +3 -6
- data/lib/action_view/helpers/tag_helper.rb +43 -37
- data/lib/action_view/helpers/tags.rb +39 -0
- data/lib/action_view/helpers/tags/base.rb +148 -0
- data/lib/action_view/helpers/tags/check_box.rb +64 -0
- data/lib/action_view/helpers/tags/checkable.rb +16 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
- data/lib/action_view/helpers/tags/collection_select.rb +28 -0
- data/lib/action_view/helpers/tags/color_field.rb +25 -0
- data/lib/action_view/helpers/tags/date_field.rb +13 -0
- data/lib/action_view/helpers/tags/date_select.rb +72 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
- data/lib/action_view/helpers/tags/email_field.rb +8 -0
- data/lib/action_view/helpers/tags/file_field.rb +8 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
- data/lib/action_view/helpers/tags/label.rb +65 -0
- data/lib/action_view/helpers/tags/month_field.rb +13 -0
- data/lib/action_view/helpers/tags/number_field.rb +18 -0
- data/lib/action_view/helpers/tags/password_field.rb +12 -0
- data/lib/action_view/helpers/tags/radio_button.rb +31 -0
- data/lib/action_view/helpers/tags/range_field.rb +8 -0
- data/lib/action_view/helpers/tags/search_field.rb +24 -0
- data/lib/action_view/helpers/tags/select.rb +41 -0
- data/lib/action_view/helpers/tags/tel_field.rb +8 -0
- data/lib/action_view/helpers/tags/text_area.rb +18 -0
- data/lib/action_view/helpers/tags/text_field.rb +29 -0
- data/lib/action_view/helpers/tags/time_field.rb +13 -0
- data/lib/action_view/helpers/tags/time_select.rb +8 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
- data/lib/action_view/helpers/tags/url_field.rb +8 -0
- data/lib/action_view/helpers/tags/week_field.rb +13 -0
- data/lib/action_view/helpers/text_helper.rb +126 -113
- data/lib/action_view/helpers/translation_helper.rb +32 -16
- data/lib/action_view/helpers/url_helper.rb +200 -271
- data/lib/action_view/locale/en.yml +1 -105
- data/lib/action_view/log_subscriber.rb +6 -4
- data/lib/action_view/lookup_context.rb +15 -39
- data/lib/action_view/model_naming.rb +12 -0
- data/lib/action_view/path_set.rb +9 -39
- data/lib/action_view/railtie.rb +6 -22
- data/lib/action_view/record_identifier.rb +84 -0
- data/lib/action_view/renderer/abstract_renderer.rb +10 -19
- data/lib/action_view/renderer/partial_renderer.rb +144 -81
- data/lib/action_view/renderer/renderer.rb +2 -19
- data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
- data/lib/action_view/renderer/template_renderer.rb +14 -13
- data/lib/action_view/routing_url_for.rb +107 -0
- data/lib/action_view/template.rb +22 -21
- data/lib/action_view/template/error.rb +22 -12
- data/lib/action_view/template/handlers.rb +12 -9
- data/lib/action_view/template/handlers/builder.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +11 -16
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/resolver.rb +111 -83
- data/lib/action_view/template/text.rb +12 -8
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/test_case.rb +66 -43
- data/lib/action_view/testing/resolvers.rb +3 -2
- data/lib/action_view/vendor/html-scanner.rb +20 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
- metadata +135 -125
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,185 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module ActionController #:nodoc:
|
4
|
-
module Caching
|
5
|
-
# Action caching is similar to page caching by the fact that the entire
|
6
|
-
# output of the response is cached, but unlike page caching, every
|
7
|
-
# request still goes through Action Pack. The key benefit of this is
|
8
|
-
# that filters run before the cache is served, which allows for
|
9
|
-
# authentication and other restrictions on whether someone is allowed
|
10
|
-
# to execute such action. Example:
|
11
|
-
#
|
12
|
-
# class ListsController < ApplicationController
|
13
|
-
# before_filter :authenticate, :except => :public
|
14
|
-
#
|
15
|
-
# caches_page :public
|
16
|
-
# caches_action :index, :show
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# In this example, the +public+ action doesn't require authentication
|
20
|
-
# so it's possible to use the faster page caching. On the other hand
|
21
|
-
# +index+ and +show+ require authentication. They can still be cached,
|
22
|
-
# but we need action caching for them.
|
23
|
-
#
|
24
|
-
# Action caching uses fragment caching internally and an around
|
25
|
-
# filter to do the job. The fragment cache is named according to
|
26
|
-
# the host and path of the request. A page that is accessed at
|
27
|
-
# <tt>http://david.example.com/lists/show/1</tt> will result in a fragment named
|
28
|
-
# <tt>david.example.com/lists/show/1</tt>. This allows the cacher to
|
29
|
-
# differentiate between <tt>david.example.com/lists/</tt> and
|
30
|
-
# <tt>jamis.example.com/lists/</tt> -- which is a helpful way of assisting
|
31
|
-
# the subdomain-as-account-key pattern.
|
32
|
-
#
|
33
|
-
# Different representations of the same resource, e.g.
|
34
|
-
# <tt>http://david.example.com/lists</tt> and
|
35
|
-
# <tt>http://david.example.com/lists.xml</tt>
|
36
|
-
# are treated like separate requests and so are cached separately.
|
37
|
-
# Keep in mind when expiring an action cache that
|
38
|
-
# <tt>:action => 'lists'</tt> is not the same as
|
39
|
-
# <tt>:action => 'list', :format => :xml</tt>.
|
40
|
-
#
|
41
|
-
# You can modify the default action cache path by passing a
|
42
|
-
# <tt>:cache_path</tt> option. This will be passed directly to
|
43
|
-
# <tt>ActionCachePath.path_for</tt>. This is handy for actions with
|
44
|
-
# multiple possible routes that should be cached differently. If a
|
45
|
-
# block is given, it is called with the current controller instance.
|
46
|
-
#
|
47
|
-
# And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a
|
48
|
-
# proc that specifies when the action should be cached.
|
49
|
-
#
|
50
|
-
# Finally, if you are using memcached, you can also pass <tt>:expires_in</tt>.
|
51
|
-
#
|
52
|
-
# The following example depicts some of the points made above:
|
53
|
-
#
|
54
|
-
# class ListsController < ApplicationController
|
55
|
-
# before_filter :authenticate, :except => :public
|
56
|
-
#
|
57
|
-
# caches_page :public
|
58
|
-
#
|
59
|
-
# caches_action :index, :if => proc do
|
60
|
-
# !request.format.json? # cache if is not a JSON request
|
61
|
-
# end
|
62
|
-
#
|
63
|
-
# caches_action :show, :cache_path => { :project => 1 },
|
64
|
-
# :expires_in => 1.hour
|
65
|
-
#
|
66
|
-
# caches_action :feed, :cache_path => proc do
|
67
|
-
# if params[:user_id]
|
68
|
-
# user_list_url(params[:user_id, params[:id])
|
69
|
-
# else
|
70
|
-
# list_url(params[:id])
|
71
|
-
# end
|
72
|
-
# end
|
73
|
-
# end
|
74
|
-
#
|
75
|
-
# If you pass <tt>:layout => false</tt>, it will only cache your action
|
76
|
-
# content. That's useful when your layout has dynamic information.
|
77
|
-
#
|
78
|
-
# Warning: If the format of the request is determined by the Accept HTTP
|
79
|
-
# header the Content-Type of the cached response could be wrong because
|
80
|
-
# no information about the MIME type is stored in the cache key. So, if
|
81
|
-
# you first ask for MIME type M in the Accept header, a cache entry is
|
82
|
-
# created, and then perform a second request to the same resource asking
|
83
|
-
# for a different MIME type, you'd get the content cached for M.
|
84
|
-
#
|
85
|
-
# The <tt>:format</tt> parameter is taken into account though. The safest
|
86
|
-
# way to cache by MIME type is to pass the format in the route.
|
87
|
-
module Actions
|
88
|
-
extend ActiveSupport::Concern
|
89
|
-
|
90
|
-
module ClassMethods
|
91
|
-
# Declares that +actions+ should be cached.
|
92
|
-
# See ActionController::Caching::Actions for details.
|
93
|
-
def caches_action(*actions)
|
94
|
-
return unless cache_configured?
|
95
|
-
options = actions.extract_options!
|
96
|
-
options[:layout] = true unless options.key?(:layout)
|
97
|
-
filter_options = options.extract!(:if, :unless).merge(:only => actions)
|
98
|
-
cache_options = options.extract!(:layout, :cache_path).merge(:store_options => options)
|
99
|
-
|
100
|
-
around_filter ActionCacheFilter.new(cache_options), filter_options
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def _save_fragment(name, options)
|
105
|
-
content = ""
|
106
|
-
response_body.each do |parts|
|
107
|
-
content << parts
|
108
|
-
end
|
109
|
-
|
110
|
-
if caching_allowed?
|
111
|
-
write_fragment(name, content, options)
|
112
|
-
else
|
113
|
-
content
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
protected
|
118
|
-
def expire_action(options = {})
|
119
|
-
return unless cache_configured?
|
120
|
-
|
121
|
-
if options.is_a?(Hash) && options[:action].is_a?(Array)
|
122
|
-
options[:action].each {|action| expire_action(options.merge(:action => action)) }
|
123
|
-
else
|
124
|
-
expire_fragment(ActionCachePath.new(self, options, false).path)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
class ActionCacheFilter #:nodoc:
|
129
|
-
def initialize(options, &block)
|
130
|
-
@cache_path, @store_options, @cache_layout =
|
131
|
-
options.values_at(:cache_path, :store_options, :layout)
|
132
|
-
end
|
133
|
-
|
134
|
-
def filter(controller)
|
135
|
-
path_options = if @cache_path.respond_to?(:call)
|
136
|
-
controller.instance_exec(controller, &@cache_path)
|
137
|
-
else
|
138
|
-
@cache_path
|
139
|
-
end
|
140
|
-
|
141
|
-
cache_path = ActionCachePath.new(controller, path_options || {})
|
142
|
-
|
143
|
-
body = controller.read_fragment(cache_path.path, @store_options)
|
144
|
-
|
145
|
-
unless body
|
146
|
-
controller.action_has_layout = false unless @cache_layout
|
147
|
-
yield
|
148
|
-
controller.action_has_layout = true
|
149
|
-
body = controller._save_fragment(cache_path.path, @store_options)
|
150
|
-
end
|
151
|
-
|
152
|
-
body = controller.render_to_string(:text => body, :layout => true) unless @cache_layout
|
153
|
-
|
154
|
-
controller.response_body = body
|
155
|
-
controller.content_type = Mime[cache_path.extension || :html]
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
class ActionCachePath
|
160
|
-
attr_reader :path, :extension
|
161
|
-
|
162
|
-
# If +infer_extension+ is true, the cache path extension is looked up from the request's
|
163
|
-
# path and format. This is desirable when reading and writing the cache, but not when
|
164
|
-
# expiring the cache - expire_action should expire the same files regardless of the
|
165
|
-
# request format.
|
166
|
-
def initialize(controller, options = {}, infer_extension = true)
|
167
|
-
if infer_extension
|
168
|
-
@extension = controller.params[:format]
|
169
|
-
options.reverse_merge!(:format => @extension) if options.is_a?(Hash)
|
170
|
-
end
|
171
|
-
|
172
|
-
path = controller.url_for(options).split(%r{://}).last
|
173
|
-
@path = normalize!(path)
|
174
|
-
end
|
175
|
-
|
176
|
-
private
|
177
|
-
def normalize!(path)
|
178
|
-
path << 'index' if path[-1] == ?/
|
179
|
-
path << ".#{extension}" if extension and !path.split('?').first.ends_with?(".#{extension}")
|
180
|
-
URI.parser.unescape(path)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
@@ -1,187 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
-
|
4
|
-
module ActionController #:nodoc:
|
5
|
-
module Caching
|
6
|
-
# Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server
|
7
|
-
# can serve without going through Action Pack. This is the fastest way to cache your content as opposed to going dynamically
|
8
|
-
# through the process of generating the content. Unfortunately, this incredible speed-up is only available to stateless pages
|
9
|
-
# where all visitors are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are
|
10
|
-
# a great fit for this approach, but account-based systems where people log in and manipulate their own data are often less
|
11
|
-
# likely candidates.
|
12
|
-
#
|
13
|
-
# Specifying which actions to cache is done through the <tt>caches_page</tt> class method:
|
14
|
-
#
|
15
|
-
# class WeblogController < ActionController::Base
|
16
|
-
# caches_page :show, :new
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# This will generate cache files such as <tt>weblog/show/5.html</tt> and <tt>weblog/new.html</tt>, which match the URLs used
|
20
|
-
# that would normally trigger dynamic page generation. Page caching works by configuring a web server to first check for the
|
21
|
-
# existence of files on disk, and to serve them directly when found, without passing the request through to Action Pack.
|
22
|
-
# This is much faster than handling the full dynamic request in the usual way.
|
23
|
-
#
|
24
|
-
# Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache
|
25
|
-
# is not restored before another hit is made against it. The API for doing so mimics the options from +url_for+ and friends:
|
26
|
-
#
|
27
|
-
# class WeblogController < ActionController::Base
|
28
|
-
# def update
|
29
|
-
# List.update(params[:list][:id], params[:list])
|
30
|
-
# expire_page :action => "show", :id => params[:list][:id]
|
31
|
-
# redirect_to :action => "show", :id => params[:list][:id]
|
32
|
-
# end
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be
|
36
|
-
# expired.
|
37
|
-
module Pages
|
38
|
-
extend ActiveSupport::Concern
|
39
|
-
|
40
|
-
included do
|
41
|
-
# The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
|
42
|
-
# For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>Rails.root + "/public"</tt>). Changing
|
43
|
-
# this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
|
44
|
-
# web server to look in the new location for cached files.
|
45
|
-
class_attribute :page_cache_directory
|
46
|
-
self.page_cache_directory ||= ''
|
47
|
-
|
48
|
-
# Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
|
49
|
-
# order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
|
50
|
-
# If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
|
51
|
-
# extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
|
52
|
-
class_attribute :page_cache_extension
|
53
|
-
self.page_cache_extension ||= '.html'
|
54
|
-
|
55
|
-
# The compression used for gzip. If false (default), the page is not compressed.
|
56
|
-
# If can be a symbol showing the ZLib compression method, for example, :best_compression
|
57
|
-
# or :best_speed or an integer configuring the compression level.
|
58
|
-
class_attribute :page_cache_compression
|
59
|
-
self.page_cache_compression ||= false
|
60
|
-
end
|
61
|
-
|
62
|
-
module ClassMethods
|
63
|
-
# Expires the page that was cached with the +path+ as a key. Example:
|
64
|
-
# expire_page "/lists/show"
|
65
|
-
def expire_page(path)
|
66
|
-
return unless perform_caching
|
67
|
-
path = page_cache_path(path)
|
68
|
-
|
69
|
-
instrument_page_cache :expire_page, path do
|
70
|
-
File.delete(path) if File.exist?(path)
|
71
|
-
File.delete(path + '.gz') if File.exist?(path + '.gz')
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Manually cache the +content+ in the key determined by +path+. Example:
|
76
|
-
# cache_page "I'm the cached content", "/lists/show"
|
77
|
-
def cache_page(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION)
|
78
|
-
return unless perform_caching
|
79
|
-
path = page_cache_path(path, extension)
|
80
|
-
|
81
|
-
instrument_page_cache :write_page, path do
|
82
|
-
FileUtils.makedirs(File.dirname(path))
|
83
|
-
File.open(path, "wb+") { |f| f.write(content) }
|
84
|
-
if gzip
|
85
|
-
Zlib::GzipWriter.open(path + '.gz', gzip) { |f| f.write(content) }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Caches the +actions+ using the page-caching approach that'll store
|
91
|
-
# the cache in a path within the page_cache_directory that
|
92
|
-
# matches the triggering url.
|
93
|
-
#
|
94
|
-
# You can also pass a :gzip option to override the class configuration one.
|
95
|
-
#
|
96
|
-
# Usage:
|
97
|
-
#
|
98
|
-
# # cache the index action
|
99
|
-
# caches_page :index
|
100
|
-
#
|
101
|
-
# # cache the index action except for JSON requests
|
102
|
-
# caches_page :index, :if => Proc.new { |c| !c.request.format.json? }
|
103
|
-
#
|
104
|
-
# # don't gzip images
|
105
|
-
# caches_page :image, :gzip => false
|
106
|
-
def caches_page(*actions)
|
107
|
-
return unless perform_caching
|
108
|
-
options = actions.extract_options!
|
109
|
-
|
110
|
-
gzip_level = options.fetch(:gzip, page_cache_compression)
|
111
|
-
gzip_level = case gzip_level
|
112
|
-
when Symbol
|
113
|
-
Zlib.const_get(gzip_level.to_s.upcase)
|
114
|
-
when Fixnum
|
115
|
-
gzip_level
|
116
|
-
when false
|
117
|
-
nil
|
118
|
-
else
|
119
|
-
Zlib::BEST_COMPRESSION
|
120
|
-
end
|
121
|
-
|
122
|
-
after_filter({:only => actions}.merge(options)) do |c|
|
123
|
-
c.cache_page(nil, nil, gzip_level)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private
|
128
|
-
def page_cache_file(path, extension)
|
129
|
-
name = (path.empty? || path == "/") ? "/index" : URI.parser.unescape(path.chomp('/'))
|
130
|
-
unless (name.split('/').last || name).include? '.'
|
131
|
-
name << (extension || self.page_cache_extension)
|
132
|
-
end
|
133
|
-
return name
|
134
|
-
end
|
135
|
-
|
136
|
-
def page_cache_path(path, extension = nil)
|
137
|
-
page_cache_directory.to_s + page_cache_file(path, extension)
|
138
|
-
end
|
139
|
-
|
140
|
-
def instrument_page_cache(name, path)
|
141
|
-
ActiveSupport::Notifications.instrument("#{name}.action_controller", :path => path){ yield }
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# Expires the page that was cached with the +options+ as a key. Example:
|
146
|
-
# expire_page :controller => "lists", :action => "show"
|
147
|
-
def expire_page(options = {})
|
148
|
-
return unless self.class.perform_caching
|
149
|
-
|
150
|
-
if options.is_a?(Hash)
|
151
|
-
if options[:action].is_a?(Array)
|
152
|
-
options[:action].each do |action|
|
153
|
-
self.class.expire_page(url_for(options.merge(:only_path => true, :action => action)))
|
154
|
-
end
|
155
|
-
else
|
156
|
-
self.class.expire_page(url_for(options.merge(:only_path => true)))
|
157
|
-
end
|
158
|
-
else
|
159
|
-
self.class.expire_page(options)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
# Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of response.body is used.
|
164
|
-
# If no options are provided, the url of the current request being handled is used. Example:
|
165
|
-
# cache_page "I'm the cached content", :controller => "lists", :action => "show"
|
166
|
-
def cache_page(content = nil, options = nil, gzip = Zlib::BEST_COMPRESSION)
|
167
|
-
return unless self.class.perform_caching && caching_allowed?
|
168
|
-
|
169
|
-
path = case options
|
170
|
-
when Hash
|
171
|
-
url_for(options.merge(:only_path => true, :format => params[:format]))
|
172
|
-
when String
|
173
|
-
options
|
174
|
-
else
|
175
|
-
request.path
|
176
|
-
end
|
177
|
-
|
178
|
-
if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
|
179
|
-
extension = ".#{type_symbol}"
|
180
|
-
end
|
181
|
-
|
182
|
-
self.class.cache_page(content || response.body, path, extension, gzip)
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
module ActionController #:nodoc:
|
2
|
-
module Caching
|
3
|
-
# Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
|
4
|
-
# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
|
5
|
-
#
|
6
|
-
# class ListSweeper < ActionController::Caching::Sweeper
|
7
|
-
# observe List, Item
|
8
|
-
#
|
9
|
-
# def after_save(record)
|
10
|
-
# list = record.is_a?(List) ? record : record.list
|
11
|
-
# expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id)
|
12
|
-
# expire_action(:controller => "lists", :action => "all")
|
13
|
-
# list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key) }
|
14
|
-
# end
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# The sweeper is assigned in the controllers that wish to have its job performed using the <tt>cache_sweeper</tt> class method:
|
18
|
-
#
|
19
|
-
# class ListsController < ApplicationController
|
20
|
-
# caches_action :index, :show, :public, :feed
|
21
|
-
# cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ]
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# In the example above, four actions are cached and three actions are responsible for expiring those caches.
|
25
|
-
#
|
26
|
-
# You can also name an explicit class in the declaration of a sweeper, which is needed if the sweeper is in a module:
|
27
|
-
#
|
28
|
-
# class ListsController < ApplicationController
|
29
|
-
# caches_action :index, :show, :public, :feed
|
30
|
-
# cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
|
31
|
-
# end
|
32
|
-
module Sweeping
|
33
|
-
extend ActiveSupport::Concern
|
34
|
-
|
35
|
-
module ClassMethods #:nodoc:
|
36
|
-
def cache_sweeper(*sweepers)
|
37
|
-
configuration = sweepers.extract_options!
|
38
|
-
|
39
|
-
sweepers.each do |sweeper|
|
40
|
-
ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
|
41
|
-
sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance
|
42
|
-
|
43
|
-
if sweeper_instance.is_a?(Sweeper)
|
44
|
-
around_filter(sweeper_instance, :only => configuration[:only])
|
45
|
-
else
|
46
|
-
after_filter(sweeper_instance, :only => configuration[:only])
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
if defined?(ActiveRecord) and defined?(ActiveRecord::Observer)
|
54
|
-
class Sweeper < ActiveRecord::Observer #:nodoc:
|
55
|
-
attr_accessor :controller
|
56
|
-
|
57
|
-
def before(controller)
|
58
|
-
self.controller = controller
|
59
|
-
callback(:before) if controller.perform_caching
|
60
|
-
true # before method from sweeper should always return true
|
61
|
-
end
|
62
|
-
|
63
|
-
def after(controller)
|
64
|
-
self.controller = controller
|
65
|
-
callback(:after) if controller.perform_caching
|
66
|
-
# Clean up, so that the controller can be collected after this request
|
67
|
-
self.controller = nil
|
68
|
-
end
|
69
|
-
|
70
|
-
protected
|
71
|
-
# gets the action cache path for the given options.
|
72
|
-
def action_path_for(options)
|
73
|
-
Actions::ActionCachePath.new(controller, options).path
|
74
|
-
end
|
75
|
-
|
76
|
-
# Retrieve instance variables set in the controller.
|
77
|
-
def assigns(key)
|
78
|
-
controller.instance_variable_get("@#{key}")
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
def callback(timing)
|
83
|
-
controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
|
84
|
-
action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"
|
85
|
-
|
86
|
-
__send__(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
|
87
|
-
__send__(action_callback_method_name) if respond_to?(action_callback_method_name, true)
|
88
|
-
end
|
89
|
-
|
90
|
-
def method_missing(method, *arguments, &block)
|
91
|
-
return unless @controller
|
92
|
-
@controller.__send__(method, *arguments, &block)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|