halorgium-actionpack 3.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5179 -0
- data/MIT-LICENSE +21 -0
- data/README +409 -0
- data/lib/abstract_controller.rb +16 -0
- data/lib/abstract_controller/base.rb +158 -0
- data/lib/abstract_controller/callbacks.rb +113 -0
- data/lib/abstract_controller/exceptions.rb +12 -0
- data/lib/abstract_controller/helpers.rb +151 -0
- data/lib/abstract_controller/layouts.rb +250 -0
- data/lib/abstract_controller/localized_cache.rb +49 -0
- data/lib/abstract_controller/logger.rb +61 -0
- data/lib/abstract_controller/rendering_controller.rb +188 -0
- data/lib/action_controller.rb +72 -0
- data/lib/action_controller/base.rb +168 -0
- data/lib/action_controller/caching.rb +80 -0
- data/lib/action_controller/caching/actions.rb +163 -0
- data/lib/action_controller/caching/fragments.rb +116 -0
- data/lib/action_controller/caching/pages.rb +154 -0
- data/lib/action_controller/caching/sweeping.rb +97 -0
- data/lib/action_controller/deprecated.rb +4 -0
- data/lib/action_controller/deprecated/integration_test.rb +2 -0
- data/lib/action_controller/deprecated/performance_test.rb +1 -0
- data/lib/action_controller/dispatch/dispatcher.rb +57 -0
- data/lib/action_controller/metal.rb +129 -0
- data/lib/action_controller/metal/benchmarking.rb +73 -0
- data/lib/action_controller/metal/compatibility.rb +145 -0
- data/lib/action_controller/metal/conditional_get.rb +86 -0
- data/lib/action_controller/metal/configuration.rb +28 -0
- data/lib/action_controller/metal/cookies.rb +105 -0
- data/lib/action_controller/metal/exceptions.rb +55 -0
- data/lib/action_controller/metal/filter_parameter_logging.rb +77 -0
- data/lib/action_controller/metal/flash.rb +162 -0
- data/lib/action_controller/metal/head.rb +27 -0
- data/lib/action_controller/metal/helpers.rb +115 -0
- data/lib/action_controller/metal/hide_actions.rb +47 -0
- data/lib/action_controller/metal/http_authentication.rb +312 -0
- data/lib/action_controller/metal/layouts.rb +171 -0
- data/lib/action_controller/metal/mime_responds.rb +317 -0
- data/lib/action_controller/metal/rack_convenience.rb +27 -0
- data/lib/action_controller/metal/redirector.rb +22 -0
- data/lib/action_controller/metal/render_options.rb +103 -0
- data/lib/action_controller/metal/rendering_controller.rb +57 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +108 -0
- data/lib/action_controller/metal/rescuable.rb +13 -0
- data/lib/action_controller/metal/responder.rb +200 -0
- data/lib/action_controller/metal/session.rb +15 -0
- data/lib/action_controller/metal/session_management.rb +45 -0
- data/lib/action_controller/metal/streaming.rb +188 -0
- data/lib/action_controller/metal/testing.rb +39 -0
- data/lib/action_controller/metal/url_for.rb +41 -0
- data/lib/action_controller/metal/verification.rb +130 -0
- data/lib/action_controller/middleware.rb +38 -0
- data/lib/action_controller/notifications.rb +10 -0
- data/lib/action_controller/polymorphic_routes.rb +183 -0
- data/lib/action_controller/record_identifier.rb +91 -0
- data/lib/action_controller/testing/process.rb +111 -0
- data/lib/action_controller/testing/test_case.rb +345 -0
- data/lib/action_controller/translation.rb +13 -0
- data/lib/action_controller/url_rewriter.rb +204 -0
- data/lib/action_controller/vendor/html-scanner.rb +16 -0
- data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +176 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_dispatch.rb +70 -0
- data/lib/action_dispatch/http/headers.rb +33 -0
- data/lib/action_dispatch/http/mime_type.rb +231 -0
- data/lib/action_dispatch/http/mime_types.rb +23 -0
- data/lib/action_dispatch/http/request.rb +539 -0
- data/lib/action_dispatch/http/response.rb +290 -0
- data/lib/action_dispatch/http/status_codes.rb +42 -0
- data/lib/action_dispatch/http/utils.rb +20 -0
- data/lib/action_dispatch/middleware/callbacks.rb +50 -0
- data/lib/action_dispatch/middleware/params_parser.rb +79 -0
- data/lib/action_dispatch/middleware/rescue.rb +26 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +208 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +235 -0
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +143 -0
- data/lib/action_dispatch/middleware/stack.rb +116 -0
- data/lib/action_dispatch/middleware/static.rb +44 -0
- data/lib/action_dispatch/middleware/string_coercion.rb +29 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +26 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +29 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +2 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +10 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +2 -0
- data/lib/action_dispatch/routing.rb +381 -0
- data/lib/action_dispatch/routing/deprecated_mapper.rb +878 -0
- data/lib/action_dispatch/routing/mapper.rb +327 -0
- data/lib/action_dispatch/routing/route.rb +49 -0
- data/lib/action_dispatch/routing/route_set.rb +497 -0
- data/lib/action_dispatch/testing/assertions.rb +8 -0
- data/lib/action_dispatch/testing/assertions/dom.rb +35 -0
- data/lib/action_dispatch/testing/assertions/model.rb +19 -0
- data/lib/action_dispatch/testing/assertions/response.rb +145 -0
- data/lib/action_dispatch/testing/assertions/routing.rb +144 -0
- data/lib/action_dispatch/testing/assertions/selector.rb +639 -0
- data/lib/action_dispatch/testing/assertions/tag.rb +123 -0
- data/lib/action_dispatch/testing/integration.rb +504 -0
- data/lib/action_dispatch/testing/performance_test.rb +15 -0
- data/lib/action_dispatch/testing/test_request.rb +83 -0
- data/lib/action_dispatch/testing/test_response.rb +131 -0
- data/lib/action_pack.rb +24 -0
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +58 -0
- data/lib/action_view/base.rb +308 -0
- data/lib/action_view/context.rb +44 -0
- data/lib/action_view/erb/util.rb +48 -0
- data/lib/action_view/helpers.rb +62 -0
- data/lib/action_view/helpers/active_model_helper.rb +306 -0
- data/lib/action_view/helpers/ajax_helper.rb +68 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +830 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
- data/lib/action_view/helpers/cache_helper.rb +39 -0
- data/lib/action_view/helpers/capture_helper.rb +168 -0
- data/lib/action_view/helpers/date_helper.rb +988 -0
- data/lib/action_view/helpers/debug_helper.rb +38 -0
- data/lib/action_view/helpers/form_helper.rb +1102 -0
- data/lib/action_view/helpers/form_options_helper.rb +600 -0
- data/lib/action_view/helpers/form_tag_helper.rb +495 -0
- data/lib/action_view/helpers/javascript_helper.rb +208 -0
- data/lib/action_view/helpers/number_helper.rb +311 -0
- data/lib/action_view/helpers/prototype_helper.rb +1309 -0
- data/lib/action_view/helpers/raw_output_helper.rb +9 -0
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +58 -0
- data/lib/action_view/helpers/sanitize_helper.rb +259 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
- data/lib/action_view/helpers/tag_helper.rb +151 -0
- data/lib/action_view/helpers/text_helper.rb +594 -0
- data/lib/action_view/helpers/translation_helper.rb +39 -0
- data/lib/action_view/helpers/url_helper.rb +639 -0
- data/lib/action_view/locale/en.yml +117 -0
- data/lib/action_view/paths.rb +80 -0
- data/lib/action_view/render/partials.rb +342 -0
- data/lib/action_view/render/rendering.rb +134 -0
- data/lib/action_view/safe_buffer.rb +28 -0
- data/lib/action_view/template/error.rb +101 -0
- data/lib/action_view/template/handler.rb +36 -0
- data/lib/action_view/template/handlers.rb +52 -0
- data/lib/action_view/template/handlers/builder.rb +17 -0
- data/lib/action_view/template/handlers/erb.rb +53 -0
- data/lib/action_view/template/handlers/rjs.rb +18 -0
- data/lib/action_view/template/resolver.rb +165 -0
- data/lib/action_view/template/template.rb +131 -0
- data/lib/action_view/template/text.rb +38 -0
- data/lib/action_view/test_case.rb +163 -0
- metadata +236 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
module ActionController
|
2
|
+
module ConditionalGet
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include RackConvenience
|
6
|
+
include Head
|
7
|
+
|
8
|
+
# Sets the etag, last_modified, or both on the response and renders a
|
9
|
+
# "304 Not Modified" response if the request is already fresh.
|
10
|
+
#
|
11
|
+
# Parameters:
|
12
|
+
# * <tt>:etag</tt>
|
13
|
+
# * <tt>:last_modified</tt>
|
14
|
+
# * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
#
|
18
|
+
# def show
|
19
|
+
# @article = Article.find(params[:id])
|
20
|
+
# fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# This will render the show template if the request isn't sending a matching etag or
|
24
|
+
# If-Modified-Since header and just a "304 Not Modified" response if there's a match.
|
25
|
+
#
|
26
|
+
def fresh_when(options)
|
27
|
+
options.assert_valid_keys(:etag, :last_modified, :public)
|
28
|
+
|
29
|
+
response.etag = options[:etag] if options[:etag]
|
30
|
+
response.last_modified = options[:last_modified] if options[:last_modified]
|
31
|
+
response.cache_control[:public] = true if options[:public]
|
32
|
+
|
33
|
+
head :not_modified if request.fresh?(response)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sets the etag and/or last_modified on the response and checks it against
|
37
|
+
# the client request. If the request doesn't match the options provided, the
|
38
|
+
# request is considered stale and should be generated from scratch. Otherwise,
|
39
|
+
# it's fresh and we don't need to generate anything and a reply of "304 Not Modified" is sent.
|
40
|
+
#
|
41
|
+
# Parameters:
|
42
|
+
# * <tt>:etag</tt>
|
43
|
+
# * <tt>:last_modified</tt>
|
44
|
+
# * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
|
45
|
+
#
|
46
|
+
# Example:
|
47
|
+
#
|
48
|
+
# def show
|
49
|
+
# @article = Article.find(params[:id])
|
50
|
+
#
|
51
|
+
# if stale?(:etag => @article, :last_modified => @article.created_at.utc)
|
52
|
+
# @statistics = @article.really_expensive_call
|
53
|
+
# respond_to do |format|
|
54
|
+
# # all the supported formats
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
def stale?(options)
|
59
|
+
fresh_when(options)
|
60
|
+
!request.fresh?(response)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that
|
64
|
+
# intermediate caches shouldn't cache the response.
|
65
|
+
#
|
66
|
+
# Examples:
|
67
|
+
# expires_in 20.minutes
|
68
|
+
# expires_in 3.hours, :public => true
|
69
|
+
# expires in 3.hours, 'max-stale' => 5.hours, :public => true
|
70
|
+
#
|
71
|
+
# This method will overwrite an existing Cache-Control header.
|
72
|
+
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
|
73
|
+
def expires_in(seconds, options = {}) #:doc:
|
74
|
+
response.cache_control.merge!(:max_age => seconds, :public => options.delete(:public))
|
75
|
+
options.delete(:private)
|
76
|
+
|
77
|
+
response.cache_control[:extras] = options.map {|k,v| "#{k}=#{v}"}
|
78
|
+
end
|
79
|
+
|
80
|
+
# Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or
|
81
|
+
# intermediate caches (like caching proxy servers).
|
82
|
+
def expires_now #:doc:
|
83
|
+
response.cache_control.replace(:no_cache => true)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ActionController
|
2
|
+
module Configuration
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def config
|
6
|
+
@config ||= self.class.config
|
7
|
+
end
|
8
|
+
|
9
|
+
def config=(config)
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def default_config
|
15
|
+
@default_config ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def config
|
19
|
+
self.config ||= default_config
|
20
|
+
end
|
21
|
+
|
22
|
+
def config=(config)
|
23
|
+
@config = ActiveSupport::OrderedHash.new
|
24
|
+
@config.merge!(config)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module ActionController #:nodoc:
|
2
|
+
# Cookies are read and written through ActionController#cookies.
|
3
|
+
#
|
4
|
+
# The cookies being read are the ones received along with the request, the cookies
|
5
|
+
# being written will be sent out with the response. Reading a cookie does not get
|
6
|
+
# the cookie object itself back, just the value it holds.
|
7
|
+
#
|
8
|
+
# Examples for writing:
|
9
|
+
#
|
10
|
+
# # Sets a simple session cookie.
|
11
|
+
# cookies[:user_name] = "david"
|
12
|
+
#
|
13
|
+
# # Sets a cookie that expires in 1 hour.
|
14
|
+
# cookies[:login] = { :value => "XJ-122", :expires => 1.hour.from_now }
|
15
|
+
#
|
16
|
+
# Examples for reading:
|
17
|
+
#
|
18
|
+
# cookies[:user_name] # => "david"
|
19
|
+
# cookies.size # => 2
|
20
|
+
#
|
21
|
+
# Example for deleting:
|
22
|
+
#
|
23
|
+
# cookies.delete :user_name
|
24
|
+
#
|
25
|
+
# Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:
|
26
|
+
#
|
27
|
+
# cookies[:key] = {
|
28
|
+
# :value => 'a yummy cookie',
|
29
|
+
# :expires => 1.year.from_now,
|
30
|
+
# :domain => 'domain.com'
|
31
|
+
# }
|
32
|
+
#
|
33
|
+
# cookies.delete(:key, :domain => 'domain.com')
|
34
|
+
#
|
35
|
+
# The option symbols for setting cookies are:
|
36
|
+
#
|
37
|
+
# * <tt>:value</tt> - The cookie's value or list of values (as an array).
|
38
|
+
# * <tt>:path</tt> - The path for which this cookie applies. Defaults to the root
|
39
|
+
# of the application.
|
40
|
+
# * <tt>:domain</tt> - The domain for which this cookie applies.
|
41
|
+
# * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
|
42
|
+
# * <tt>:secure</tt> - Whether this cookie is a only transmitted to HTTPS servers.
|
43
|
+
# Default is +false+.
|
44
|
+
# * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
|
45
|
+
# only HTTP. Defaults to +false+.
|
46
|
+
module Cookies
|
47
|
+
extend ActiveSupport::Concern
|
48
|
+
|
49
|
+
include RackConvenience
|
50
|
+
|
51
|
+
included do
|
52
|
+
helper_method :cookies
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
# Returns the cookie container, which operates as described above.
|
57
|
+
def cookies
|
58
|
+
@cookies ||= CookieJar.build(request, response)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class CookieJar < Hash #:nodoc:
|
63
|
+
def self.build(request, response)
|
64
|
+
new.tap do |hash|
|
65
|
+
hash.update(request.cookies)
|
66
|
+
hash.response = response
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
attr_accessor :response
|
71
|
+
|
72
|
+
# Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
|
73
|
+
def [](name)
|
74
|
+
super(name.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Sets the cookie named +name+. The second argument may be the very cookie
|
78
|
+
# value, or a hash of options as documented above.
|
79
|
+
def []=(key, options)
|
80
|
+
if options.is_a?(Hash)
|
81
|
+
options.symbolize_keys!
|
82
|
+
value = options[:value]
|
83
|
+
else
|
84
|
+
value = options
|
85
|
+
options = { :value => value }
|
86
|
+
end
|
87
|
+
|
88
|
+
super(key.to_s, value)
|
89
|
+
|
90
|
+
options[:path] ||= "/"
|
91
|
+
response.set_cookie(key, options)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Removes the cookie on the client machine by setting the value to an empty string
|
95
|
+
# and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
|
96
|
+
# an options hash to delete cookies with extra data such as a <tt>:path</tt>.
|
97
|
+
def delete(key, options = {})
|
98
|
+
options.symbolize_keys!
|
99
|
+
options[:path] ||= "/"
|
100
|
+
value = super(key.to_s)
|
101
|
+
response.delete_cookie(key, options)
|
102
|
+
value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module ActionController
|
2
|
+
class ActionControllerError < StandardError #:nodoc:
|
3
|
+
end
|
4
|
+
|
5
|
+
class RenderError < ActionControllerError #:nodoc:
|
6
|
+
end
|
7
|
+
|
8
|
+
class RoutingError < ActionControllerError #:nodoc:
|
9
|
+
attr_reader :failures
|
10
|
+
def initialize(message, failures=[])
|
11
|
+
super(message)
|
12
|
+
@failures = failures
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MethodNotAllowed < ActionControllerError #:nodoc:
|
17
|
+
attr_reader :allowed_methods
|
18
|
+
|
19
|
+
def initialize(*allowed_methods)
|
20
|
+
super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
|
21
|
+
@allowed_methods = allowed_methods
|
22
|
+
end
|
23
|
+
|
24
|
+
def allowed_methods_header
|
25
|
+
allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', '
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_response!(response)
|
29
|
+
response.headers['Allow'] ||= allowed_methods_header
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class NotImplemented < MethodNotAllowed #:nodoc:
|
34
|
+
end
|
35
|
+
|
36
|
+
class UnknownController < ActionControllerError #:nodoc:
|
37
|
+
end
|
38
|
+
|
39
|
+
class MissingFile < ActionControllerError #:nodoc:
|
40
|
+
end
|
41
|
+
|
42
|
+
class RenderError < ActionControllerError #:nodoc:
|
43
|
+
end
|
44
|
+
|
45
|
+
class SessionOverflowError < ActionControllerError #:nodoc:
|
46
|
+
DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
|
47
|
+
|
48
|
+
def initialize(message = nil)
|
49
|
+
super(message || DEFAULT_MESSAGE)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class UnknownHttpMethod < ActionControllerError #:nodoc:
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module ActionController
|
2
|
+
module FilterParameterLogging
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include AbstractController::Logger
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Replace sensitive parameter data from the request log.
|
9
|
+
# Filters parameters that have any of the arguments as a substring.
|
10
|
+
# Looks in all subhashes of the param hash for keys to filter.
|
11
|
+
# If a block is given, each key and value of the parameter hash and all
|
12
|
+
# subhashes is passed to it, the value or key
|
13
|
+
# can be replaced using String#replace or similar method.
|
14
|
+
#
|
15
|
+
# Examples:
|
16
|
+
#
|
17
|
+
# filter_parameter_logging :password
|
18
|
+
# => replaces the value to all keys matching /password/i with "[FILTERED]"
|
19
|
+
#
|
20
|
+
# filter_parameter_logging :foo, "bar"
|
21
|
+
# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
22
|
+
#
|
23
|
+
# filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
|
24
|
+
# => reverses the value to all keys matching /secret/i
|
25
|
+
#
|
26
|
+
# filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
|
27
|
+
# => reverses the value to all keys matching /secret/i, and
|
28
|
+
# replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
29
|
+
def filter_parameter_logging(*filter_words, &block)
|
30
|
+
raise "You must filter at least one word from logging" if filter_words.empty?
|
31
|
+
|
32
|
+
parameter_filter = Regexp.new(filter_words.join('|'), true)
|
33
|
+
|
34
|
+
define_method(:filter_parameters) do |original_params|
|
35
|
+
filtered_params = {}
|
36
|
+
|
37
|
+
original_params.each do |key, value|
|
38
|
+
if key =~ parameter_filter
|
39
|
+
value = '[FILTERED]'
|
40
|
+
elsif value.is_a?(Hash)
|
41
|
+
value = filter_parameters(value)
|
42
|
+
elsif value.is_a?(Array)
|
43
|
+
value = value.map { |item| filter_parameters(item) }
|
44
|
+
elsif block_given?
|
45
|
+
key = key.dup
|
46
|
+
value = value.dup if value.duplicable?
|
47
|
+
yield key, value
|
48
|
+
end
|
49
|
+
|
50
|
+
filtered_params[key] = value
|
51
|
+
end
|
52
|
+
|
53
|
+
filtered_params
|
54
|
+
end
|
55
|
+
protected :filter_parameters
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
INTERNAL_PARAMS = [:controller, :action, :format, :_method, :only_path]
|
60
|
+
|
61
|
+
def process(*)
|
62
|
+
response = super
|
63
|
+
if logger
|
64
|
+
parameters = filter_parameters(params).except!(*INTERNAL_PARAMS)
|
65
|
+
logger.info { " Parameters: #{parameters.inspect}" } unless parameters.empty?
|
66
|
+
end
|
67
|
+
response
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def filter_parameters(params)
|
73
|
+
params.dup
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module ActionController #:nodoc:
|
2
|
+
# The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed
|
3
|
+
# to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
|
4
|
+
# action that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can
|
5
|
+
# then expose the flash to its template. Actually, that exposure is automatically done. Example:
|
6
|
+
#
|
7
|
+
# class PostsController < ActionController::Base
|
8
|
+
# def create
|
9
|
+
# # save post
|
10
|
+
# flash[:notice] = "Successfully created post"
|
11
|
+
# redirect_to posts_path(@post)
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def show
|
15
|
+
# # doesn't need to assign the flash notice to the template, that's done automatically
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# show.html.erb
|
20
|
+
# <% if flash[:notice] %>
|
21
|
+
# <div class="notice"><%= flash[:notice] %></div>
|
22
|
+
# <% end %>
|
23
|
+
#
|
24
|
+
# This example just places a string in the flash, but you can put any object in there. And of course, you can put as
|
25
|
+
# many as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
|
26
|
+
#
|
27
|
+
# See docs on the FlashHash class for more details about the flash.
|
28
|
+
module Flash
|
29
|
+
extend ActiveSupport::Concern
|
30
|
+
|
31
|
+
include Session
|
32
|
+
|
33
|
+
class FlashNow #:nodoc:
|
34
|
+
def initialize(flash)
|
35
|
+
@flash = flash
|
36
|
+
end
|
37
|
+
|
38
|
+
def []=(k, v)
|
39
|
+
@flash[k] = v
|
40
|
+
@flash.discard(k)
|
41
|
+
v
|
42
|
+
end
|
43
|
+
|
44
|
+
def [](k)
|
45
|
+
@flash[k]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class FlashHash < Hash
|
50
|
+
def initialize #:nodoc:
|
51
|
+
super
|
52
|
+
@used = Set.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def []=(k, v) #:nodoc:
|
56
|
+
keep(k)
|
57
|
+
super
|
58
|
+
end
|
59
|
+
|
60
|
+
def update(h) #:nodoc:
|
61
|
+
h.keys.each { |k| keep(k) }
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
alias :merge! :update
|
66
|
+
|
67
|
+
def replace(h) #:nodoc:
|
68
|
+
@used = Set.new
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sets a flash that will not be available to the next action, only to the current.
|
73
|
+
#
|
74
|
+
# flash.now[:message] = "Hello current action"
|
75
|
+
#
|
76
|
+
# This method enables you to use the flash as a central messaging system in your app.
|
77
|
+
# When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>).
|
78
|
+
# When you need to pass an object to the current action, you use <tt>now</tt>, and your object will
|
79
|
+
# vanish when the current action is done.
|
80
|
+
#
|
81
|
+
# Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
|
82
|
+
def now
|
83
|
+
FlashNow.new(self)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Keeps either the entire current flash or a specific flash entry available for the next action:
|
87
|
+
#
|
88
|
+
# flash.keep # keeps the entire flash
|
89
|
+
# flash.keep(:notice) # keeps only the "notice" entry, the rest of the flash is discarded
|
90
|
+
def keep(k = nil)
|
91
|
+
use(k, false)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Marks the entire flash or a single flash entry to be discarded by the end of the current action:
|
95
|
+
#
|
96
|
+
# flash.discard # discard the entire flash at the end of the current action
|
97
|
+
# flash.discard(:warning) # discard only the "warning" entry at the end of the current action
|
98
|
+
def discard(k = nil)
|
99
|
+
use(k)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Mark for removal entries that were kept, and delete unkept ones.
|
103
|
+
#
|
104
|
+
# This method is called automatically by filters, so you generally don't need to care about it.
|
105
|
+
def sweep #:nodoc:
|
106
|
+
keys.each do |k|
|
107
|
+
unless @used.include?(k)
|
108
|
+
@used << k
|
109
|
+
else
|
110
|
+
delete(k)
|
111
|
+
@used.delete(k)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# clean up after keys that could have been left over by calling reject! or shift on the flash
|
116
|
+
(@used - keys).each{ |k| @used.delete(k) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def store(session)
|
120
|
+
return if self.empty?
|
121
|
+
session["flash"] = self
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
# Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
|
126
|
+
# use() # marks the entire flash as used
|
127
|
+
# use('msg') # marks the "msg" entry as used
|
128
|
+
# use(nil, false) # marks the entire flash as unused (keeps it around for one more action)
|
129
|
+
# use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
|
130
|
+
# Returns the single value for the key you asked to be marked (un)used or the FlashHash itself
|
131
|
+
# if no key is passed.
|
132
|
+
def use(key = nil, used = true)
|
133
|
+
Array(key || keys).each { |k| used ? @used << k : @used.delete(k) }
|
134
|
+
return key ? self[key] : self
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
protected
|
139
|
+
def process_action(method_name)
|
140
|
+
super
|
141
|
+
@_flash.store(session) if @_flash
|
142
|
+
@_flash = nil
|
143
|
+
end
|
144
|
+
|
145
|
+
def reset_session
|
146
|
+
super
|
147
|
+
@_flash = nil
|
148
|
+
end
|
149
|
+
|
150
|
+
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to
|
151
|
+
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
|
152
|
+
# to put a new one.
|
153
|
+
def flash #:doc:
|
154
|
+
unless @_flash
|
155
|
+
@_flash = session["flash"] || FlashHash.new
|
156
|
+
@_flash.sweep
|
157
|
+
end
|
158
|
+
|
159
|
+
@_flash
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|