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.

Files changed (161) hide show
  1. data/CHANGELOG +88 -142
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +5 -6
  4. data/lib/abstract_controller.rb +1 -0
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +24 -19
  7. data/lib/abstract_controller/callbacks.rb +19 -19
  8. data/lib/abstract_controller/helpers.rb +11 -13
  9. data/lib/abstract_controller/layouts.rb +4 -5
  10. data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
  11. data/lib/abstract_controller/rendering.rb +34 -31
  12. data/lib/abstract_controller/url_for.rb +27 -0
  13. data/lib/abstract_controller/view_paths.rb +31 -6
  14. data/lib/action_controller.rb +5 -3
  15. data/lib/action_controller/base.rb +15 -16
  16. data/lib/action_controller/caching.rb +2 -2
  17. data/lib/action_controller/caching/actions.rb +11 -12
  18. data/lib/action_controller/caching/fragments.rb +41 -19
  19. data/lib/action_controller/caching/pages.rb +3 -9
  20. data/lib/action_controller/caching/sweeping.rb +0 -1
  21. data/lib/action_controller/deprecated.rb +1 -1
  22. data/lib/action_controller/log_subscriber.rb +1 -1
  23. data/lib/action_controller/metal.rb +78 -20
  24. data/lib/action_controller/metal/compatibility.rb +0 -9
  25. data/lib/action_controller/metal/conditional_get.rb +9 -9
  26. data/lib/action_controller/metal/data_streaming.rb +145 -0
  27. data/lib/action_controller/metal/force_ssl.rb +35 -0
  28. data/lib/action_controller/metal/head.rb +1 -1
  29. data/lib/action_controller/metal/helpers.rb +37 -44
  30. data/lib/action_controller/metal/hide_actions.rb +2 -3
  31. data/lib/action_controller/metal/http_authentication.rb +41 -38
  32. data/lib/action_controller/metal/implicit_render.rb +13 -13
  33. data/lib/action_controller/metal/instrumentation.rb +2 -2
  34. data/lib/action_controller/metal/mime_responds.rb +25 -19
  35. data/lib/action_controller/metal/params_wrapper.rb +224 -0
  36. data/lib/action_controller/metal/redirecting.rb +6 -2
  37. data/lib/action_controller/metal/renderers.rb +50 -36
  38. data/lib/action_controller/metal/rendering.rb +34 -25
  39. data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
  40. data/lib/action_controller/metal/responder.rb +47 -12
  41. data/lib/action_controller/metal/streaming.rb +244 -138
  42. data/lib/action_controller/metal/testing.rb +0 -9
  43. data/lib/action_controller/metal/url_for.rb +12 -14
  44. data/lib/action_controller/railtie.rb +19 -37
  45. data/lib/action_controller/railties/paths.rb +24 -0
  46. data/lib/action_controller/record_identifier.rb +4 -10
  47. data/lib/action_controller/test_case.rb +36 -19
  48. data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
  49. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
  50. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
  51. data/lib/action_dispatch.rb +4 -1
  52. data/lib/action_dispatch/http/cache.rb +5 -32
  53. data/lib/action_dispatch/http/filter_parameters.rb +3 -1
  54. data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
  55. data/lib/action_dispatch/http/mime_type.rb +45 -5
  56. data/lib/action_dispatch/http/rack_cache.rb +58 -0
  57. data/lib/action_dispatch/http/request.rb +27 -41
  58. data/lib/action_dispatch/http/response.rb +56 -54
  59. data/lib/action_dispatch/http/upload.rb +1 -11
  60. data/lib/action_dispatch/http/url.rb +102 -42
  61. data/lib/action_dispatch/middleware/callbacks.rb +8 -25
  62. data/lib/action_dispatch/middleware/closed_error.rb +7 -0
  63. data/lib/action_dispatch/middleware/cookies.rb +37 -15
  64. data/lib/action_dispatch/middleware/flash.rb +80 -11
  65. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  66. data/lib/action_dispatch/middleware/reloader.rb +76 -0
  67. data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
  68. data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
  69. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
  70. data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
  71. data/lib/action_dispatch/middleware/stack.rb +50 -17
  72. data/lib/action_dispatch/middleware/static.rb +41 -29
  73. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
  74. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  75. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
  76. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
  77. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
  78. data/lib/action_dispatch/railtie.rb +8 -0
  79. data/lib/action_dispatch/routing.rb +13 -1
  80. data/lib/action_dispatch/routing/mapper.rb +345 -227
  81. data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
  82. data/lib/action_dispatch/routing/redirection.rb +110 -0
  83. data/lib/action_dispatch/routing/route.rb +15 -13
  84. data/lib/action_dispatch/routing/route_set.rb +116 -90
  85. data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
  86. data/lib/action_dispatch/routing/url_for.rb +25 -1
  87. data/lib/action_dispatch/testing/assertions/response.rb +8 -10
  88. data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
  89. data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
  90. data/lib/action_dispatch/testing/integration.rb +37 -28
  91. data/lib/action_dispatch/testing/performance_test.rb +1 -3
  92. data/lib/action_dispatch/testing/test_process.rb +1 -1
  93. data/lib/action_dispatch/testing/test_request.rb +9 -3
  94. data/lib/action_dispatch/testing/test_response.rb +4 -111
  95. data/lib/action_pack.rb +1 -1
  96. data/lib/action_pack/version.rb +3 -3
  97. data/lib/action_view.rb +39 -24
  98. data/lib/action_view/base.rb +61 -86
  99. data/lib/action_view/buffers.rb +43 -0
  100. data/lib/action_view/context.rb +21 -24
  101. data/lib/action_view/flows.rb +79 -0
  102. data/lib/action_view/helpers.rb +8 -6
  103. data/lib/action_view/helpers/active_model_helper.rb +0 -23
  104. data/lib/action_view/helpers/asset_paths.rb +79 -0
  105. data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
  106. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
  107. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
  108. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
  109. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
  110. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  111. data/lib/action_view/helpers/cache_helper.rb +11 -19
  112. data/lib/action_view/helpers/capture_helper.rb +19 -8
  113. data/lib/action_view/helpers/controller_helper.rb +21 -0
  114. data/lib/action_view/helpers/csrf_helper.rb +22 -4
  115. data/lib/action_view/helpers/date_helper.rb +36 -22
  116. data/lib/action_view/helpers/form_helper.rb +199 -113
  117. data/lib/action_view/helpers/form_options_helper.rb +10 -11
  118. data/lib/action_view/helpers/form_tag_helper.rb +94 -22
  119. data/lib/action_view/helpers/javascript_helper.rb +24 -107
  120. data/lib/action_view/helpers/number_helper.rb +36 -33
  121. data/lib/action_view/helpers/output_safety_helper.rb +38 -0
  122. data/lib/action_view/helpers/record_tag_helper.rb +6 -6
  123. data/lib/action_view/helpers/rendering_helper.rb +90 -0
  124. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  125. data/lib/action_view/helpers/sprockets_helper.rb +69 -0
  126. data/lib/action_view/helpers/tag_helper.rb +34 -12
  127. data/lib/action_view/helpers/text_helper.rb +30 -145
  128. data/lib/action_view/helpers/translation_helper.rb +10 -17
  129. data/lib/action_view/helpers/url_helper.rb +70 -67
  130. data/lib/action_view/locale/en.yml +1 -1
  131. data/lib/action_view/lookup_context.rb +36 -14
  132. data/lib/action_view/{paths.rb → path_set.rb} +9 -8
  133. data/lib/action_view/railtie.rb +12 -4
  134. data/lib/action_view/renderer/abstract_renderer.rb +36 -0
  135. data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
  136. data/lib/action_view/renderer/renderer.rb +54 -0
  137. data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
  138. data/lib/action_view/renderer/template_renderer.rb +74 -0
  139. data/lib/action_view/template.rb +91 -54
  140. data/lib/action_view/template/error.rb +11 -8
  141. data/lib/action_view/template/handler.rb +9 -1
  142. data/lib/action_view/template/handlers.rb +9 -9
  143. data/lib/action_view/template/handlers/builder.rb +4 -4
  144. data/lib/action_view/template/handlers/erb.rb +21 -41
  145. data/lib/action_view/template/resolver.rb +171 -57
  146. data/lib/action_view/template/text.rb +0 -4
  147. data/lib/action_view/test_case.rb +32 -16
  148. data/lib/action_view/testing/resolvers.rb +16 -10
  149. data/lib/sprockets/railtie.rb +100 -0
  150. metadata +162 -140
  151. checksums.yaml +0 -7
  152. data/lib/action_controller/deprecated/base.rb +0 -143
  153. data/lib/action_controller/deprecated/dispatcher.rb +0 -28
  154. data/lib/action_controller/deprecated/url_writer.rb +0 -14
  155. data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
  156. data/lib/action_view/helpers/prototype_helper.rb +0 -851
  157. data/lib/action_view/helpers/raw_output_helper.rb +0 -18
  158. data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
  159. data/lib/action_view/render/layouts.rb +0 -83
  160. data/lib/action_view/render/rendering.rb +0 -67
  161. data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -1,21 +1,21 @@
1
1
  module ActionController
2
2
  module ImplicitRender
3
- def send_action(*)
4
- ret = super
5
- default_render unless response_body
6
- ret
3
+ def send_action(method, *args)
4
+ if respond_to?(method, true)
5
+ ret = super
6
+ default_render unless response_body
7
+ ret
8
+ else
9
+ default_render
10
+ end
7
11
  end
8
12
 
9
- def default_render
10
- render
13
+ def default_render(*args)
14
+ render(*args)
11
15
  end
12
16
 
13
- def method_for_action(action_name)
14
- super || begin
15
- if template_exists?(action_name.to_s, _prefix)
16
- "default_render"
17
- end
18
- end
17
+ def action_method?(action_name)
18
+ super || template_exists?(action_name.to_s, _prefixes)
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -14,7 +14,7 @@ module ActionController
14
14
 
15
15
  attr_internal :view_runtime
16
16
 
17
- def process_action(action, *args)
17
+ def process_action(*args)
18
18
  raw_payload = {
19
19
  :controller => self.class.name,
20
20
  :action => self.action_name,
@@ -78,7 +78,7 @@ module ActionController
78
78
  yield
79
79
  end
80
80
 
81
- # Everytime after an action is processed, this method is invoked
81
+ # Every time after an action is processed, this method is invoked
82
82
  # with the payload, so you can add more information.
83
83
  # :api: plugin
84
84
  def append_info_to_payload(payload) #:nodoc:
@@ -1,10 +1,13 @@
1
1
  require 'abstract_controller/collector'
2
2
  require 'active_support/core_ext/class/attribute'
3
+ require 'active_support/core_ext/object/inclusion'
3
4
 
4
5
  module ActionController #:nodoc:
5
- module MimeResponds #:nodoc:
6
+ module MimeResponds
6
7
  extend ActiveSupport::Concern
7
8
 
9
+ include ActionController::ImplicitRender
10
+
8
11
  included do
9
12
  class_attribute :responder, :mimes_for_respond_to
10
13
  self.responder = ActionController::Responder
@@ -32,10 +35,10 @@ module ActionController #:nodoc:
32
35
  # and all actions except <tt>:edit</tt> respond to <tt>:xml</tt> and
33
36
  # <tt>:json</tt>.
34
37
  #
35
- # respond_to :rjs, :only => :create
38
+ # respond_to :json, :only => :create
36
39
  #
37
40
  # This specifies that the <tt>:create</tt> action and no other responds
38
- # to <tt>:rjs</tt>.
41
+ # to <tt>:json</tt>.
39
42
  def respond_to(*mimes)
40
43
  options = mimes.extract_options!
41
44
 
@@ -63,13 +66,13 @@ module ActionController #:nodoc:
63
66
  # might look something like this:
64
67
  #
65
68
  # def index
66
- # @people = Person.find(:all)
69
+ # @people = Person.all
67
70
  # end
68
71
  #
69
72
  # Here's the same action, with web-service support baked in:
70
73
  #
71
74
  # def index
72
- # @people = Person.find(:all)
75
+ # @people = Person.all
73
76
  #
74
77
  # respond_to do |format|
75
78
  # format.html
@@ -105,8 +108,8 @@ module ActionController #:nodoc:
105
108
  # end
106
109
  # end
107
110
  #
108
- # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
109
- # (format.js), then it is an RJS request and we render the RJS template associated with this action.
111
+ # If the client wants HTML, we just redirect them back to the person list. If they want JavaScript,
112
+ # then it is an Ajax request and we render the JavaScript template associated with this action.
110
113
  # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
111
114
  # include the person's company in the rendered XML, so you get something like this:
112
115
  #
@@ -155,7 +158,7 @@ module ActionController #:nodoc:
155
158
  # Respond to also allows you to specify a common block for different formats by using any:
156
159
  #
157
160
  # def index
158
- # @people = Person.find(:all)
161
+ # @people = Person.all
159
162
  #
160
163
  # respond_to do |format|
161
164
  # format.html
@@ -178,7 +181,7 @@ module ActionController #:nodoc:
178
181
  # respond_to :html, :xml, :json
179
182
  #
180
183
  # def index
181
- # @people = Person.find(:all)
184
+ # @people = Person.all
182
185
  # respond_with(@person)
183
186
  # end
184
187
  # end
@@ -189,7 +192,7 @@ module ActionController #:nodoc:
189
192
  raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
190
193
 
191
194
  if response = retrieve_response_from_mimes(mimes, &block)
192
- response.call
195
+ response.call(nil)
193
196
  end
194
197
  end
195
198
 
@@ -208,8 +211,8 @@ module ActionController #:nodoc:
208
211
  # It also accepts a block to be given. It's used to overwrite a default
209
212
  # response:
210
213
  #
211
- # def destroy
212
- # @user = User.find(params[:id])
214
+ # def create
215
+ # @user = User.new(params[:user])
213
216
  # flash[:notice] = "User was successfully created." if @user.save
214
217
  #
215
218
  # respond_with(@user) do |format|
@@ -222,6 +225,9 @@ module ActionController #:nodoc:
222
225
  # is quite simple (it just needs to respond to call), you can even give
223
226
  # a proc to it.
224
227
  #
228
+ # In order to use respond_with, first you need to declare the formats your
229
+ # controller responds to in the class level with a call to <tt>respond_to</tt>.
230
+ #
225
231
  def respond_with(*resources, &block)
226
232
  raise "In order to use respond_with, first you need to declare the formats your " <<
227
233
  "controller responds to in the class level" if self.class.mimes_for_respond_to.empty?
@@ -245,9 +251,9 @@ module ActionController #:nodoc:
245
251
  config = self.class.mimes_for_respond_to[mime]
246
252
 
247
253
  if config[:except]
248
- !config[:except].include?(action)
254
+ !action.in?(config[:except])
249
255
  elsif config[:only]
250
- config[:only].include?(action)
256
+ action.in?(config[:only])
251
257
  else
252
258
  true
253
259
  end
@@ -257,10 +263,9 @@ module ActionController #:nodoc:
257
263
  # Collects mimes and return the response for the negotiated format. Returns
258
264
  # nil if :not_acceptable was sent to the client.
259
265
  #
260
- def retrieve_response_from_mimes(mimes=nil, &block)
261
- collector = Collector.new { default_render }
266
+ def retrieve_response_from_mimes(mimes=nil, &block) #:nodoc:
262
267
  mimes ||= collect_mimes_from_class_level
263
- mimes.each { |mime| collector.send(mime) }
268
+ collector = Collector.new(mimes) { |options| default_render(options || {}) }
264
269
  block.call(collector) if block_given?
265
270
 
266
271
  if format = request.negotiate_mime(collector.order)
@@ -277,8 +282,9 @@ module ActionController #:nodoc:
277
282
  include AbstractController::Collector
278
283
  attr_accessor :order
279
284
 
280
- def initialize(&block)
285
+ def initialize(mimes, &block)
281
286
  @order, @responses, @default_response = [], {}, block
287
+ mimes.each { |mime| send(mime) }
282
288
  end
283
289
 
284
290
  def any(*args, &block)
@@ -291,7 +297,7 @@ module ActionController #:nodoc:
291
297
  alias :all :any
292
298
 
293
299
  def custom(mime_type, &block)
294
- mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s)
300
+ mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
295
301
  @order << mime_type
296
302
  @responses[mime_type] ||= block
297
303
  end
@@ -0,0 +1,224 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'active_support/core_ext/hash/slice'
3
+ require 'active_support/core_ext/hash/except'
4
+ require 'active_support/core_ext/array/wrap'
5
+ require 'action_dispatch/http/mime_types'
6
+
7
+ module ActionController
8
+ # Wraps parameters hash into nested hash. This will allow client to submit
9
+ # POST request without having to specify a root element in it.
10
+ #
11
+ # By default this functionality won't be enabled. You can enable
12
+ # it globally by setting +ActionController::Base.wrap_parameters+:
13
+ #
14
+ # ActionController::Base.wrap_parameters = [:json]
15
+ #
16
+ # You could also turn it on per controller by setting the format array to
17
+ # non-empty array:
18
+ #
19
+ # class UsersController < ApplicationController
20
+ # wrap_parameters :format => [:json, :xml]
21
+ # end
22
+ #
23
+ # If you enable +ParamsWrapper+ for +:json+ format. Instead of having to
24
+ # send JSON parameters like this:
25
+ #
26
+ # {"user": {"name": "Konata"}}
27
+ #
28
+ # You can now just send a parameters like this:
29
+ #
30
+ # {"name": "Konata"}
31
+ #
32
+ # And it will be wrapped into a nested hash with the key name matching
33
+ # controller's name. For example, if you're posting to +UsersController+,
34
+ # your new +params+ hash will look like this:
35
+ #
36
+ # {"name" => "Konata", "user" => {"name" => "Konata"}}
37
+ #
38
+ # You can also specify the key in which the parameters should be wrapped to,
39
+ # and also the list of attributes it should wrap by using either +:only+ or
40
+ # +:except+ options like this:
41
+ #
42
+ # class UsersController < ApplicationController
43
+ # wrap_parameters :person, :only => [:username, :password]
44
+ # end
45
+ #
46
+ # If you're going to pass the parameters to an +ActiveModel+ object (such as
47
+ # +User.new(params[:user])+), you might consider passing the model class to
48
+ # the method instead. The +ParamsWrapper+ will actually try to determine the
49
+ # list of attribute names from the model and only wrap those attributes:
50
+ #
51
+ # class UsersController < ApplicationController
52
+ # wrap_parameters Person
53
+ # end
54
+ #
55
+ # You still could pass +:only+ and +:except+ to set the list of attributes
56
+ # you want to wrap.
57
+ #
58
+ # By default, if you don't specify the key in which the parameters would be
59
+ # wrapped to, +ParamsWrapper+ will actually try to determine if there's
60
+ # a model related to it or not. This controller, for example:
61
+ #
62
+ # class Admin::UsersController < ApplicationController
63
+ # end
64
+ #
65
+ # will try to check if +Admin::User+ or +User+ model exists, and use it to
66
+ # determine the wrapper key respectively. If both of the model doesn't exists,
67
+ # it will then fallback to use +user+ as the key.
68
+ module ParamsWrapper
69
+ extend ActiveSupport::Concern
70
+
71
+ EXCLUDE_PARAMETERS = %w(authenticity_token _method utf8)
72
+
73
+ included do
74
+ class_attribute :_wrapper_options
75
+ self._wrapper_options = {:format => []}
76
+ end
77
+
78
+ module ClassMethods
79
+ # Sets the name of the wrapper key, or the model which +ParamsWrapper+
80
+ # would use to determine the attribute names from.
81
+ #
82
+ # ==== Examples
83
+ # wrap_parameters :format => :xml
84
+ # # enables the parmeter wrapper for XML format
85
+ #
86
+ # wrap_parameters :person
87
+ # # wraps parameters into +params[:person]+ hash
88
+ #
89
+ # wrap_parameters Person
90
+ # # wraps parameters by determine the wrapper key from Person class
91
+ # (+person+, in this case) and the list of attribute names
92
+ #
93
+ # wrap_parameters :only => [:username, :title]
94
+ # # wraps only +:username+ and +:title+ attributes from parameters.
95
+ #
96
+ # wrap_parameters false
97
+ # # disable parameters wrapping for this controller altogether.
98
+ #
99
+ # ==== Options
100
+ # * <tt>:format</tt> - The list of formats in which the parameters wrapper
101
+ # will be enabled.
102
+ # * <tt>:only</tt> - The list of attribute names which parameters wrapper
103
+ # will wrap into a nested hash.
104
+ # * <tt>:except</tt> - The list of attribute names which parameters wrapper
105
+ # will exclude from a nested hash.
106
+ def wrap_parameters(name_or_model_or_options, options = {})
107
+ model = nil
108
+
109
+ case name_or_model_or_options
110
+ when Hash
111
+ options = name_or_model_or_options
112
+ when false
113
+ options = options.merge(:format => [])
114
+ when Symbol, String
115
+ options = options.merge(:name => name_or_model_or_options)
116
+ else
117
+ model = name_or_model_or_options
118
+ end
119
+
120
+ _set_wrapper_defaults(_wrapper_options.slice(:format).merge(options), model)
121
+ end
122
+
123
+ # Sets the default wrapper key or model which will be used to determine
124
+ # wrapper key and attribute names. Will be called automatically when the
125
+ # module is inherited.
126
+ def inherited(klass)
127
+ if klass._wrapper_options[:format].present?
128
+ klass._set_wrapper_defaults(klass._wrapper_options)
129
+ end
130
+ super
131
+ end
132
+
133
+ protected
134
+
135
+ # Determine the wrapper model from the controller's name. By convention,
136
+ # this could be done by trying to find the defined model that has the
137
+ # same singularize name as the controller. For example, +UsersController+
138
+ # will try to find if the +User+ model exists.
139
+ def _default_wrap_model
140
+ model_name = self.name.sub(/Controller$/, '').singularize
141
+
142
+ begin
143
+ model_klass = model_name.constantize
144
+ rescue NameError => e
145
+ unscoped_model_name = model_name.split("::", 2).last
146
+ break if unscoped_model_name == model_name
147
+ model_name = unscoped_model_name
148
+ end until model_klass
149
+
150
+ model_klass
151
+ end
152
+
153
+ def _set_wrapper_defaults(options, model=nil)
154
+ options = options.dup
155
+
156
+ unless options[:only] || options[:except]
157
+ model ||= _default_wrap_model
158
+ if model.respond_to?(:column_names)
159
+ options[:only] = model.column_names
160
+ end
161
+ end
162
+
163
+ unless options[:name]
164
+ model ||= _default_wrap_model
165
+ options[:name] = model ? model.to_s.demodulize.underscore :
166
+ controller_name.singularize
167
+ end
168
+
169
+ options[:only] = Array.wrap(options[:only]).collect(&:to_s) if options[:only]
170
+ options[:except] = Array.wrap(options[:except]).collect(&:to_s) if options[:except]
171
+ options[:format] = Array.wrap(options[:format])
172
+
173
+ self._wrapper_options = options
174
+ end
175
+ end
176
+
177
+ # Performs parameters wrapping upon the request. Will be called automatically
178
+ # by the metal call stack.
179
+ def process_action(*args)
180
+ if _wrapper_enabled?
181
+ wrapped_hash = _wrap_parameters request.request_parameters
182
+ wrapped_filtered_hash = _wrap_parameters request.filtered_parameters
183
+
184
+ # This will make the wrapped hash accessible from controller and view
185
+ request.parameters.merge! wrapped_hash
186
+ request.request_parameters.merge! wrapped_hash
187
+
188
+ # This will make the wrapped hash displayed in the log file
189
+ request.filtered_parameters.merge! wrapped_filtered_hash
190
+ end
191
+ super
192
+ end
193
+
194
+ private
195
+
196
+ # Returns the wrapper key which will use to stored wrapped parameters.
197
+ def _wrapper_key
198
+ _wrapper_options[:name]
199
+ end
200
+
201
+ # Returns the list of enabled formats.
202
+ def _wrapper_formats
203
+ _wrapper_options[:format]
204
+ end
205
+
206
+ # Returns the list of parameters which will be selected for wrapped.
207
+ def _wrap_parameters(parameters)
208
+ value = if only = _wrapper_options[:only]
209
+ parameters.slice(*only)
210
+ else
211
+ except = _wrapper_options[:except] || []
212
+ parameters.except(*(except + EXCLUDE_PARAMETERS))
213
+ end
214
+
215
+ { _wrapper_key => value }
216
+ end
217
+
218
+ # Checks if we should perform parameters wrapping.
219
+ def _wrapper_enabled?
220
+ ref = request.content_mime_type.try(:ref)
221
+ _wrapper_formats.include?(ref) && !request.request_parameters[_wrapper_key]
222
+ end
223
+ end
224
+ end
@@ -20,6 +20,7 @@ module ActionController
20
20
  # * <tt>Record</tt> - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record.
21
21
  # * <tt>String</tt> starting with <tt>protocol://</tt> (like <tt>http://</tt>) - Is passed straight through as the target for redirection.
22
22
  # * <tt>String</tt> not containing a protocol - The current protocol and host is prepended to the string.
23
+ # * <tt>Proc</tt> - A block that will be executed in the controller's context. Should return any option accepted by +redirect_to+.
23
24
  # * <tt>:back</tt> - Back to the page that issued the request. Useful for forms that are triggered from multiple places.
24
25
  # Short-hand for <tt>redirect_to(request.env["HTTP_REFERER"])</tt>
25
26
  #
@@ -30,6 +31,7 @@ module ActionController
30
31
  # redirect_to "/images/screenshot.jpg"
31
32
  # redirect_to articles_url
32
33
  # redirect_to :back
34
+ # redirect_to proc { edit_post_url(@post) }
33
35
  #
34
36
  # The redirection happens as a "302 Moved" header unless otherwise specified.
35
37
  #
@@ -38,7 +40,7 @@ module ActionController
38
40
  # redirect_to :action=>'atom', :status => :moved_permanently
39
41
  # redirect_to post_url(@post), :status => 301
40
42
  # redirect_to :action=>'atom', :status => 302
41
- #
43
+ #
42
44
  # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
43
45
  # integer, or a symbol representing the downcased, underscored and symbolized description.
44
46
  #
@@ -85,9 +87,11 @@ module ActionController
85
87
  when :back
86
88
  raise RedirectBackError unless refer = request.headers["Referer"]
87
89
  refer
90
+ when Proc
91
+ _compute_redirect_to_location options.call
88
92
  else
89
93
  url_for(options)
90
- end.gsub(/[\0\r\n]/, '')
94
+ end.gsub(/[\r\n]/, '')
91
95
  end
92
96
  end
93
97
  end