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
@@ -6,7 +6,7 @@ module ActionController
6
6
  include Head
7
7
 
8
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.
9
+ # <tt>304 Not Modified</tt> response if the request is already fresh.
10
10
  #
11
11
  # Parameters:
12
12
  # * <tt>:etag</tt>
@@ -17,11 +17,11 @@ module ActionController
17
17
  #
18
18
  # def show
19
19
  # @article = Article.find(params[:id])
20
- # fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true)
20
+ # fresh_when(:etag => @article, :last_modified => @article.created_at, :public => true)
21
21
  # end
22
22
  #
23
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.
24
+ # If-Modified-Since header and just a <tt>304 Not Modified</tt> response if there's a match.
25
25
  #
26
26
  def fresh_when(options)
27
27
  options.assert_valid_keys(:etag, :last_modified, :public)
@@ -36,7 +36,7 @@ module ActionController
36
36
  # Sets the etag and/or last_modified on the response and checks it against
37
37
  # the client request. If the request doesn't match the options provided, the
38
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.
39
+ # it's fresh and we don't need to generate anything and a reply of <tt>304 Not Modified</tt> is sent.
40
40
  #
41
41
  # Parameters:
42
42
  # * <tt>:etag</tt>
@@ -48,7 +48,7 @@ module ActionController
48
48
  # def show
49
49
  # @article = Article.find(params[:id])
50
50
  #
51
- # if stale?(:etag => @article, :last_modified => @article.created_at.utc)
51
+ # if stale?(:etag => @article, :last_modified => @article.created_at)
52
52
  # @statistics = @article.really_expensive_call
53
53
  # respond_to do |format|
54
54
  # # all the supported formats
@@ -60,13 +60,13 @@ module ActionController
60
60
  !request.fresh?(response)
61
61
  end
62
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.
63
+ # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a <tt>private</tt> instruction, so that
64
+ # intermediate caches must not cache the response.
65
65
  #
66
66
  # Examples:
67
67
  # expires_in 20.minutes
68
68
  # expires_in 3.hours, :public => true
69
- # expires in 3.hours, 'max-stale' => 5.hours, :public => true
69
+ # expires_in 3.hours, 'max-stale' => 5.hours, :public => true
70
70
  #
71
71
  # This method will overwrite an existing Cache-Control header.
72
72
  # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
@@ -77,7 +77,7 @@ module ActionController
77
77
  response.cache_control[:extras] = options.map {|k,v| "#{k}=#{v}"}
78
78
  end
79
79
 
80
- # Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or
80
+ # Sets a HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should occur by the browser or
81
81
  # intermediate caches (like caching proxy servers).
82
82
  def expires_now #:doc:
83
83
  response.cache_control.replace(:no_cache => true)
@@ -0,0 +1,145 @@
1
+ require 'active_support/core_ext/file/path'
2
+
3
+ module ActionController #:nodoc:
4
+ # Methods for sending arbitrary data and for streaming files to the browser,
5
+ # instead of rendering.
6
+ module DataStreaming
7
+ extend ActiveSupport::Concern
8
+
9
+ include ActionController::Rendering
10
+
11
+ DEFAULT_SEND_FILE_OPTIONS = {
12
+ :type => 'application/octet-stream'.freeze,
13
+ :disposition => 'attachment'.freeze,
14
+ }.freeze
15
+
16
+ protected
17
+ # Sends the file. This uses a server-appropriate method (such as X-Sendfile)
18
+ # via the Rack::Sendfile middleware. The header to use is set via
19
+ # config.action_dispatch.x_sendfile_header, and defaults to "X-Sendfile".
20
+ # Your server can also configure this for you by setting the X-Sendfile-Type header.
21
+ #
22
+ # Be careful to sanitize the path parameter if it is coming from a web
23
+ # page. <tt>send_file(params[:path])</tt> allows a malicious user to
24
+ # download any file on your server.
25
+ #
26
+ # Options:
27
+ # * <tt>:filename</tt> - suggests a filename for the browser to use.
28
+ # Defaults to <tt>File.basename(path)</tt>.
29
+ # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
30
+ # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
31
+ # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
32
+ # Valid values are 'inline' and 'attachment' (default).
33
+ # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
34
+ # * <tt>:url_based_filename</tt> - set to +true+ if you want the browser guess the filename from
35
+ # the URL, which is necessary for i18n filenames on certain browsers
36
+ # (setting <tt>:filename</tt> overrides this option).
37
+ #
38
+ # The default Content-Type and Content-Disposition headers are
39
+ # set to download arbitrary binary files in as many browsers as
40
+ # possible. IE versions 4, 5, 5.5, and 6 are all known to have
41
+ # a variety of quirks (especially when downloading over SSL).
42
+ #
43
+ # Simple download:
44
+ #
45
+ # send_file '/path/to.zip'
46
+ #
47
+ # Show a JPEG in the browser:
48
+ #
49
+ # send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
50
+ #
51
+ # Show a 404 page in the browser:
52
+ #
53
+ # send_file '/path/to/404.html', :type => 'text/html; charset=utf-8', :status => 404
54
+ #
55
+ # Read about the other Content-* HTTP headers if you'd like to
56
+ # provide the user with more information (such as Content-Description) in
57
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
58
+ #
59
+ # Also be aware that the document may be cached by proxies and browsers.
60
+ # The Pragma and Cache-Control headers declare how the file may be cached
61
+ # by intermediaries. They default to require clients to validate with
62
+ # the server before releasing cached responses. See
63
+ # http://www.mnot.net/cache_docs/ for an overview of web caching and
64
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
65
+ # for the Cache-Control header spec.
66
+ def send_file(path, options = {}) #:doc:
67
+ raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
68
+
69
+ options[:filename] ||= File.basename(path) unless options[:url_based_filename]
70
+ send_file_headers! options
71
+
72
+ self.status = options[:status] || 200
73
+ self.content_type = options[:content_type] if options.key?(:content_type)
74
+ self.response_body = File.open(path, "rb")
75
+ end
76
+
77
+ # Sends the given binary data to the browser. This method is similar to
78
+ # <tt>render :text => data</tt>, but also allows you to specify whether
79
+ # the browser should display the response as a file attachment (i.e. in a
80
+ # download dialog) or as inline data. You may also set the content type,
81
+ # the apparent file name, and other things.
82
+ #
83
+ # Options:
84
+ # * <tt>:filename</tt> - suggests a filename for the browser to use.
85
+ # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
86
+ # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
87
+ # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
88
+ # Valid values are 'inline' and 'attachment' (default).
89
+ # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
90
+ #
91
+ # Generic data download:
92
+ #
93
+ # send_data buffer
94
+ #
95
+ # Download a dynamically-generated tarball:
96
+ #
97
+ # send_data generate_tgz('dir'), :filename => 'dir.tgz'
98
+ #
99
+ # Display an image Active Record in the browser:
100
+ #
101
+ # send_data image.data, :type => image.content_type, :disposition => 'inline'
102
+ #
103
+ # See +send_file+ for more information on HTTP Content-* headers and caching.
104
+ def send_data(data, options = {}) #:doc:
105
+ send_file_headers! options.dup
106
+ render options.slice(:status, :content_type).merge(:text => data)
107
+ end
108
+
109
+ private
110
+ def send_file_headers!(options)
111
+ options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
112
+ [:type, :disposition].each do |arg|
113
+ raise ArgumentError, ":#{arg} option required" if options[arg].nil?
114
+ end
115
+
116
+ disposition = options[:disposition]
117
+ disposition += %(; filename="#{options[:filename]}") if options[:filename]
118
+
119
+ content_type = options[:type]
120
+
121
+ if content_type.is_a?(Symbol)
122
+ extension = Mime[content_type]
123
+ raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension
124
+ self.content_type = extension
125
+ else
126
+ self.content_type = content_type
127
+ end
128
+
129
+ headers.merge!(
130
+ 'Content-Disposition' => disposition,
131
+ 'Content-Transfer-Encoding' => 'binary'
132
+ )
133
+
134
+ response.sending_file = true
135
+
136
+ # Fix a problem with IE 6.0 on opening downloaded files:
137
+ # If Cache-Control: no-cache is set (which Rails does by default),
138
+ # IE removes the file it just downloaded from its cache immediately
139
+ # after it displays the "open/save" dialog, which means that if you
140
+ # hit "open" the file isn't there anymore when the application that
141
+ # is called for handling the download is run, so let's workaround that
142
+ response.cache_control[:public] ||= false
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,35 @@
1
+ module ActionController
2
+ # This module provides a method which will redirects browser to use HTTPS
3
+ # protocol. This will ensure that user's sensitive information will be
4
+ # transferred safely over the internet. You _should_ always force browser
5
+ # to use HTTPS when you're transferring sensitive information such as
6
+ # user authentication, account information, or credit card information.
7
+ #
8
+ # Note that if you really concern about your application safety, you might
9
+ # consider using +config.force_ssl+ in your configuration config file instead.
10
+ # That will ensure all the data transferred via HTTPS protocol and prevent
11
+ # user from getting session hijacked when accessing the site under unsecured
12
+ # HTTP protocol.
13
+ module ForceSSL
14
+ extend ActiveSupport::Concern
15
+ include AbstractController::Callbacks
16
+
17
+ module ClassMethods
18
+ # Force the request to this particular controller or specified actions to be
19
+ # under HTTPS protocol.
20
+ #
21
+ # Note that this method will not be effective on development environment.
22
+ #
23
+ # ==== Options
24
+ # * <tt>only</tt> - The callback should be run only for this action
25
+ # * <tt>except<tt> - The callback should be run for all actions except this action
26
+ def force_ssl(options = {})
27
+ before_filter(options) do
28
+ if !request.ssl? && !Rails.env.development?
29
+ redirect_to :protocol => 'https://', :status => :moved_permanently
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -20,7 +20,7 @@ module ActionController
20
20
  location = options.delete(:location)
21
21
 
22
22
  options.each do |key, value|
23
- headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
23
+ headers[key.to_s.dasherize.split('-').each { |v| v[0] = v[0].chr.upcase }.join('-')] = value.to_s
24
24
  end
25
25
 
26
26
  self.status = status
@@ -2,21 +2,21 @@ require 'active_support/core_ext/array/wrap'
2
2
  require 'active_support/core_ext/class/attribute'
3
3
 
4
4
  module ActionController
5
- # The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+,
6
- # +numbers+ and model objects, to name a few. These helpers are available to all templates
5
+ # The \Rails framework provides a large number of helpers for working with assets, dates, forms,
6
+ # numbers and model objects, to name a few. These helpers are available to all templates
7
7
  # by default.
8
8
  #
9
- # In addition to using the standard template helpers provided in the Rails framework, creating custom helpers to
9
+ # In addition to using the standard template helpers provided, creating custom helpers to
10
10
  # extract complicated logic or reusable functionality is strongly encouraged. By default, the controller will
11
11
  # include a helper whose name matches that of the controller, e.g., <tt>MyController</tt> will automatically
12
12
  # include <tt>MyHelper</tt>.
13
13
  #
14
- # Additional helpers can be specified using the +helper+ class method in <tt>ActionController::Base</tt> or any
14
+ # Additional helpers can be specified using the +helper+ class method in ActionController::Base or any
15
15
  # controller which inherits from it.
16
16
  #
17
17
  # ==== Examples
18
- # The +to_s+ method from the Time class can be wrapped in a helper method to display a custom message if
19
- # the Time object is blank:
18
+ # The +to_s+ method from the \Time class can be wrapped in a helper method to display a custom message if
19
+ # a \Time object is blank:
20
20
  #
21
21
  # module FormattedTimeHelper
22
22
  # def format_time(time, format=:long, blank_message="&nbsp;")
@@ -53,30 +53,20 @@ module ActionController
53
53
  include AbstractController::Helpers
54
54
 
55
55
  included do
56
- config_accessor :helpers_path
56
+ config_accessor :helpers_path, :include_all_helpers
57
57
  self.helpers_path ||= []
58
+ self.include_all_helpers = true
58
59
  end
59
60
 
60
61
  module ClassMethods
61
- def helpers_dir
62
- ActiveSupport::Deprecation.warn "helpers_dir is deprecated, use helpers_path instead", caller
63
- self.helpers_path
64
- end
65
-
66
- def helpers_dir=(value)
67
- ActiveSupport::Deprecation.warn "helpers_dir= is deprecated, use helpers_path= instead", caller
68
- self.helpers_path = Array.wrap(value)
69
- end
70
-
71
62
  # Declares helper accessors for controller attributes. For example, the
72
63
  # following adds new +name+ and <tt>name=</tt> instance methods to a
73
64
  # controller and makes them available to the view:
74
- # helper_attr :name
75
65
  # attr_accessor :name
66
+ # helper_attr :name
76
67
  #
77
68
  # ==== Parameters
78
- # *attrs<Array[String, Symbol]>:: Names of attributes to be converted
79
- # into helpers.
69
+ # * <tt>attrs</tt> - Names of attributes to be converted into helpers.
80
70
  def helper_attr(*attrs)
81
71
  attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
82
72
  end
@@ -86,32 +76,35 @@ module ActionController
86
76
  @helper_proxy ||= ActionView::Base.new.extend(_helpers)
87
77
  end
88
78
 
89
- private
90
- # Overwrite modules_for_helpers to accept :all as argument, which loads
91
- # all helpers in helpers_dir.
92
- #
93
- # ==== Parameters
94
- # args<Array[String, Symbol, Module, all]>:: A list of helpers
95
- #
96
- # ==== Returns
97
- # Array[Module]:: A normalized list of modules for the list of
98
- # helpers provided.
99
- def modules_for_helpers(args)
100
- args += all_application_helpers if args.delete(:all)
101
- super(args)
102
- end
79
+ # Overwrite modules_for_helpers to accept :all as argument, which loads
80
+ # all helpers in helpers_path.
81
+ #
82
+ # ==== Parameters
83
+ # * <tt>args</tt> - A list of helpers
84
+ #
85
+ # ==== Returns
86
+ # * <tt>array</tt> - A normalized list of modules for the list of helpers provided.
87
+ def modules_for_helpers(args)
88
+ args += all_application_helpers if args.delete(:all)
89
+ super(args)
90
+ end
103
91
 
104
- # Extract helper names from files in app/helpers/**/*_helper.rb
105
- def all_application_helpers
106
- helpers = []
107
- Array.wrap(helpers_path).each do |path|
108
- extract = /^#{Regexp.quote(path.to_s)}\/?(.*)_helper.rb$/
109
- helpers += Dir["#{path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
110
- end
111
- helpers.sort!
112
- helpers.uniq!
113
- helpers
92
+ def all_helpers_from_path(path)
93
+ helpers = []
94
+ Array.wrap(path).each do |_path|
95
+ extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
96
+ helpers += Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
114
97
  end
98
+ helpers.sort!
99
+ helpers.uniq!
100
+ helpers
101
+ end
102
+
103
+ private
104
+ # Extract helper names from files in <tt>app/helpers/**/*_helper.rb</tt>
105
+ def all_application_helpers
106
+ all_helpers_from_path(helpers_path)
107
+ end
115
108
  end
116
109
  end
117
110
  end
@@ -1,8 +1,7 @@
1
1
  require 'active_support/core_ext/class/attribute'
2
2
 
3
3
  module ActionController
4
- # ActionController::HideActions adds the ability to prevent public methods on a controller
5
- # to be called as actions.
4
+ # Adds the ability to prevent public methods on a controller to be called as actions.
6
5
  module HideActions
7
6
  extend ActiveSupport::Concern
8
7
 
@@ -23,7 +22,7 @@ module ActionController
23
22
  # Sets all of the actions passed in as hidden actions.
24
23
  #
25
24
  # ==== Parameters
26
- # *args<#to_s>:: A list of actions
25
+ # * <tt>args</tt> - A list of actions
27
26
  def hide_action(*args)
28
27
  self.hidden_actions = hidden_actions.dup.merge(args.map(&:to_s)).freeze
29
28
  end
@@ -3,14 +3,12 @@ require 'active_support/core_ext/object/blank'
3
3
 
4
4
  module ActionController
5
5
  module HttpAuthentication
6
- # Makes it dead easy to do HTTP Basic authentication.
6
+ # Makes it dead easy to do HTTP \Basic and \Digest authentication.
7
7
  #
8
- # Simple Basic example:
8
+ # === Simple \Basic example
9
9
  #
10
10
  # class PostsController < ApplicationController
11
- # USER_NAME, PASSWORD = "dhh", "secret"
12
- #
13
- # before_filter :authenticate, :except => [ :index ]
11
+ # http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
14
12
  #
15
13
  # def index
16
14
  # render :text => "Everyone can see me!"
@@ -19,17 +17,11 @@ module ActionController
19
17
  # def edit
20
18
  # render :text => "I'm only accessible if you know the password"
21
19
  # end
20
+ # end
22
21
  #
23
- # private
24
- # def authenticate
25
- # authenticate_or_request_with_http_basic do |user_name, password|
26
- # user_name == USER_NAME && password == PASSWORD
27
- # end
28
- # end
29
- # end
22
+ # === Advanced \Basic example
30
23
  #
31
- #
32
- # Here is a more advanced Basic example where only Atom feeds and the XML API is protected by HTTP authentication,
24
+ # Here is a more advanced \Basic example where only Atom feeds and the XML API is protected by HTTP authentication,
33
25
  # the regular HTML interface is protected by a session approach:
34
26
  #
35
27
  # class ApplicationController < ActionController::Base
@@ -69,13 +61,13 @@ module ActionController
69
61
  # assert_equal 200, status
70
62
  # end
71
63
  #
72
- # Simple Digest example:
64
+ # === Simple \Digest example
73
65
  #
74
66
  # require 'digest/md5'
75
67
  # class PostsController < ApplicationController
76
68
  # REALM = "SuperSecret"
77
69
  # USERS = {"dhh" => "secret", #plain text password
78
- # "dap" => Digest:MD5::hexdigest(["dap",REALM,"secret"].join(":")) #ha1 digest password
70
+ # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":")) #ha1 digest password
79
71
  #
80
72
  # before_filter :authenticate, :except => [:index]
81
73
  #
@@ -101,15 +93,30 @@ module ActionController
101
93
  # or the ha1 digest hash so the framework can appropriately hash to check the user's
102
94
  # credentials. Returning +nil+ will cause authentication to fail.
103
95
  #
104
- # On shared hosts, Apache sometimes doesn't pass authentication headers to
105
- # FCGI instances. If your environment matches this description and you cannot
106
- # authenticate, try this rule in your Apache setup:
96
+ # Storing the ha1 hash: MD5(username:realm:password), is better than storing a plain password. If
97
+ # the password file or database is compromised, the attacker would be able to use the ha1 hash to
98
+ # authenticate as the user at this +realm+, but would not have the user's password to try using at
99
+ # other sites.
107
100
  #
108
- # RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
101
+ # In rare instances, web servers or front proxies strip authorization headers before
102
+ # they reach your application. You can debug this situation by logging all environment
103
+ # variables, and check for HTTP_AUTHORIZATION, amongst others.
109
104
  module Basic
110
105
  extend self
111
106
 
112
107
  module ControllerMethods
108
+ extend ActiveSupport::Concern
109
+
110
+ module ClassMethods
111
+ def http_basic_authenticate_with(options = {})
112
+ before_filter(options.except(:name, :password, :realm)) do
113
+ authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
114
+ name == options[:name] && password == options[:password]
115
+ end
116
+ end
117
+ end
118
+ end
119
+
113
120
  def authenticate_or_request_with_http_basic(realm = "Application", &login_procedure)
114
121
  authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm)
115
122
  end
@@ -209,7 +216,7 @@ module ActionController
209
216
 
210
217
  def encode_credentials(http_method, credentials, password, password_is_ha1)
211
218
  credentials[:response] = expected_response(http_method, credentials[:uri], credentials, password, password_is_ha1)
212
- "Digest " + credentials.sort_by {|x| x[0].to_s }.inject([]) {|a, v| a << "#{v[0]}='#{v[1]}'" }.join(', ')
219
+ "Digest " + credentials.sort_by {|x| x[0].to_s }.map {|v| "#{v[0]}='#{v[1]}'" }.join(', ')
213
220
  end
214
221
 
215
222
  def decode_credentials_header(request)
@@ -217,9 +224,9 @@ module ActionController
217
224
  end
218
225
 
219
226
  def decode_credentials(header)
220
- HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/,'').split(',').map do |pair|
227
+ Hash[header.to_s.gsub(/^Digest\s+/,'').split(',').map do |pair|
221
228
  key, value = pair.split('=', 2)
222
- [key.strip, value.to_s.gsub(/^"|"$/,'').delete('\'')]
229
+ [key.strip.to_sym, value.to_s.gsub(/^"|"$/,'').gsub(/'/, '')]
223
230
  end]
224
231
  end
225
232
 
@@ -373,7 +380,6 @@ module ActionController
373
380
  #
374
381
  # RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
375
382
  module Token
376
-
377
383
  extend self
378
384
 
379
385
  module ControllerMethods
@@ -402,7 +408,7 @@ module ActionController
402
408
  # Returns nil if no token is found.
403
409
  def authenticate(controller, &login_procedure)
404
410
  token, options = token_and_options(controller.request)
405
- if !token.blank?
411
+ unless token.blank?
406
412
  login_procedure.call(token, options)
407
413
  end
408
414
  end
@@ -412,20 +418,19 @@ module ActionController
412
418
  # Authorization: Token token="abc", nonce="def"
413
419
  # Then the returned token is "abc", and the options is {:nonce => "def"}
414
420
  #
415
- # request - ActionController::Request instance with the current headers.
421
+ # request - ActionDispatch::Request instance with the current headers.
416
422
  #
417
423
  # Returns an Array of [String, Hash] if a token is present.
418
424
  # Returns nil if no token is found.
419
425
  def token_and_options(request)
420
426
  if header = request.authorization.to_s[/^Token (.*)/]
421
- values = $1.split(',').
422
- inject({}) do |memo, value|
423
- value.strip! # remove any spaces between commas and values
424
- key, value = value.split(/\=\"?/) # split key=value pairs
425
- value.chomp!('"') # chomp trailing " in value
426
- value.gsub!(/\\\"/, '"') # unescape remaining quotes
427
- memo.update(key => value)
428
- end
427
+ values = Hash[$1.split(',').map do |value|
428
+ value.strip! # remove any spaces between commas and values
429
+ key, value = value.split(/\=\"?/) # split key=value pairs
430
+ value.chomp!('"') # chomp trailing " in value
431
+ value.gsub!(/\\\"/, '"') # unescape remaining quotes
432
+ [key, value]
433
+ end]
429
434
  [values.delete("token"), values.with_indifferent_access]
430
435
  end
431
436
  end
@@ -437,9 +442,8 @@ module ActionController
437
442
  #
438
443
  # Returns String.
439
444
  def encode_credentials(token, options = {})
440
- values = ["token=#{token.to_s.inspect}"]
441
- options.each do |key, value|
442
- values << "#{key}=#{value.to_s.inspect}"
445
+ values = ["token=#{token.to_s.inspect}"] + options.map do |key, value|
446
+ "#{key}=#{value.to_s.inspect}"
443
447
  end
444
448
  "Token #{values * ", "}"
445
449
  end
@@ -455,6 +459,5 @@ module ActionController
455
459
  controller.__send__ :render, :text => "HTTP Token: Access denied.\n", :status => :unauthorized
456
460
  end
457
461
  end
458
-
459
462
  end
460
463
  end