halorgium-actionpack 3.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data/CHANGELOG +5179 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +409 -0
  4. data/lib/abstract_controller.rb +16 -0
  5. data/lib/abstract_controller/base.rb +158 -0
  6. data/lib/abstract_controller/callbacks.rb +113 -0
  7. data/lib/abstract_controller/exceptions.rb +12 -0
  8. data/lib/abstract_controller/helpers.rb +151 -0
  9. data/lib/abstract_controller/layouts.rb +250 -0
  10. data/lib/abstract_controller/localized_cache.rb +49 -0
  11. data/lib/abstract_controller/logger.rb +61 -0
  12. data/lib/abstract_controller/rendering_controller.rb +188 -0
  13. data/lib/action_controller.rb +72 -0
  14. data/lib/action_controller/base.rb +168 -0
  15. data/lib/action_controller/caching.rb +80 -0
  16. data/lib/action_controller/caching/actions.rb +163 -0
  17. data/lib/action_controller/caching/fragments.rb +116 -0
  18. data/lib/action_controller/caching/pages.rb +154 -0
  19. data/lib/action_controller/caching/sweeping.rb +97 -0
  20. data/lib/action_controller/deprecated.rb +4 -0
  21. data/lib/action_controller/deprecated/integration_test.rb +2 -0
  22. data/lib/action_controller/deprecated/performance_test.rb +1 -0
  23. data/lib/action_controller/dispatch/dispatcher.rb +57 -0
  24. data/lib/action_controller/metal.rb +129 -0
  25. data/lib/action_controller/metal/benchmarking.rb +73 -0
  26. data/lib/action_controller/metal/compatibility.rb +145 -0
  27. data/lib/action_controller/metal/conditional_get.rb +86 -0
  28. data/lib/action_controller/metal/configuration.rb +28 -0
  29. data/lib/action_controller/metal/cookies.rb +105 -0
  30. data/lib/action_controller/metal/exceptions.rb +55 -0
  31. data/lib/action_controller/metal/filter_parameter_logging.rb +77 -0
  32. data/lib/action_controller/metal/flash.rb +162 -0
  33. data/lib/action_controller/metal/head.rb +27 -0
  34. data/lib/action_controller/metal/helpers.rb +115 -0
  35. data/lib/action_controller/metal/hide_actions.rb +47 -0
  36. data/lib/action_controller/metal/http_authentication.rb +312 -0
  37. data/lib/action_controller/metal/layouts.rb +171 -0
  38. data/lib/action_controller/metal/mime_responds.rb +317 -0
  39. data/lib/action_controller/metal/rack_convenience.rb +27 -0
  40. data/lib/action_controller/metal/redirector.rb +22 -0
  41. data/lib/action_controller/metal/render_options.rb +103 -0
  42. data/lib/action_controller/metal/rendering_controller.rb +57 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +108 -0
  44. data/lib/action_controller/metal/rescuable.rb +13 -0
  45. data/lib/action_controller/metal/responder.rb +200 -0
  46. data/lib/action_controller/metal/session.rb +15 -0
  47. data/lib/action_controller/metal/session_management.rb +45 -0
  48. data/lib/action_controller/metal/streaming.rb +188 -0
  49. data/lib/action_controller/metal/testing.rb +39 -0
  50. data/lib/action_controller/metal/url_for.rb +41 -0
  51. data/lib/action_controller/metal/verification.rb +130 -0
  52. data/lib/action_controller/middleware.rb +38 -0
  53. data/lib/action_controller/notifications.rb +10 -0
  54. data/lib/action_controller/polymorphic_routes.rb +183 -0
  55. data/lib/action_controller/record_identifier.rb +91 -0
  56. data/lib/action_controller/testing/process.rb +111 -0
  57. data/lib/action_controller/testing/test_case.rb +345 -0
  58. data/lib/action_controller/translation.rb +13 -0
  59. data/lib/action_controller/url_rewriter.rb +204 -0
  60. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  61. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  62. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +176 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  65. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  66. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  67. data/lib/action_dispatch.rb +70 -0
  68. data/lib/action_dispatch/http/headers.rb +33 -0
  69. data/lib/action_dispatch/http/mime_type.rb +231 -0
  70. data/lib/action_dispatch/http/mime_types.rb +23 -0
  71. data/lib/action_dispatch/http/request.rb +539 -0
  72. data/lib/action_dispatch/http/response.rb +290 -0
  73. data/lib/action_dispatch/http/status_codes.rb +42 -0
  74. data/lib/action_dispatch/http/utils.rb +20 -0
  75. data/lib/action_dispatch/middleware/callbacks.rb +50 -0
  76. data/lib/action_dispatch/middleware/params_parser.rb +79 -0
  77. data/lib/action_dispatch/middleware/rescue.rb +26 -0
  78. data/lib/action_dispatch/middleware/session/abstract_store.rb +208 -0
  79. data/lib/action_dispatch/middleware/session/cookie_store.rb +235 -0
  80. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
  81. data/lib/action_dispatch/middleware/show_exceptions.rb +143 -0
  82. data/lib/action_dispatch/middleware/stack.rb +116 -0
  83. data/lib/action_dispatch/middleware/static.rb +44 -0
  84. data/lib/action_dispatch/middleware/string_coercion.rb +29 -0
  85. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +24 -0
  86. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +26 -0
  87. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
  88. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +29 -0
  89. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +2 -0
  90. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +10 -0
  91. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +21 -0
  92. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +2 -0
  93. data/lib/action_dispatch/routing.rb +381 -0
  94. data/lib/action_dispatch/routing/deprecated_mapper.rb +878 -0
  95. data/lib/action_dispatch/routing/mapper.rb +327 -0
  96. data/lib/action_dispatch/routing/route.rb +49 -0
  97. data/lib/action_dispatch/routing/route_set.rb +497 -0
  98. data/lib/action_dispatch/testing/assertions.rb +8 -0
  99. data/lib/action_dispatch/testing/assertions/dom.rb +35 -0
  100. data/lib/action_dispatch/testing/assertions/model.rb +19 -0
  101. data/lib/action_dispatch/testing/assertions/response.rb +145 -0
  102. data/lib/action_dispatch/testing/assertions/routing.rb +144 -0
  103. data/lib/action_dispatch/testing/assertions/selector.rb +639 -0
  104. data/lib/action_dispatch/testing/assertions/tag.rb +123 -0
  105. data/lib/action_dispatch/testing/integration.rb +504 -0
  106. data/lib/action_dispatch/testing/performance_test.rb +15 -0
  107. data/lib/action_dispatch/testing/test_request.rb +83 -0
  108. data/lib/action_dispatch/testing/test_response.rb +131 -0
  109. data/lib/action_pack.rb +24 -0
  110. data/lib/action_pack/version.rb +9 -0
  111. data/lib/action_view.rb +58 -0
  112. data/lib/action_view/base.rb +308 -0
  113. data/lib/action_view/context.rb +44 -0
  114. data/lib/action_view/erb/util.rb +48 -0
  115. data/lib/action_view/helpers.rb +62 -0
  116. data/lib/action_view/helpers/active_model_helper.rb +306 -0
  117. data/lib/action_view/helpers/ajax_helper.rb +68 -0
  118. data/lib/action_view/helpers/asset_tag_helper.rb +830 -0
  119. data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
  120. data/lib/action_view/helpers/cache_helper.rb +39 -0
  121. data/lib/action_view/helpers/capture_helper.rb +168 -0
  122. data/lib/action_view/helpers/date_helper.rb +988 -0
  123. data/lib/action_view/helpers/debug_helper.rb +38 -0
  124. data/lib/action_view/helpers/form_helper.rb +1102 -0
  125. data/lib/action_view/helpers/form_options_helper.rb +600 -0
  126. data/lib/action_view/helpers/form_tag_helper.rb +495 -0
  127. data/lib/action_view/helpers/javascript_helper.rb +208 -0
  128. data/lib/action_view/helpers/number_helper.rb +311 -0
  129. data/lib/action_view/helpers/prototype_helper.rb +1309 -0
  130. data/lib/action_view/helpers/raw_output_helper.rb +9 -0
  131. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  132. data/lib/action_view/helpers/record_tag_helper.rb +58 -0
  133. data/lib/action_view/helpers/sanitize_helper.rb +259 -0
  134. data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
  135. data/lib/action_view/helpers/tag_helper.rb +151 -0
  136. data/lib/action_view/helpers/text_helper.rb +594 -0
  137. data/lib/action_view/helpers/translation_helper.rb +39 -0
  138. data/lib/action_view/helpers/url_helper.rb +639 -0
  139. data/lib/action_view/locale/en.yml +117 -0
  140. data/lib/action_view/paths.rb +80 -0
  141. data/lib/action_view/render/partials.rb +342 -0
  142. data/lib/action_view/render/rendering.rb +134 -0
  143. data/lib/action_view/safe_buffer.rb +28 -0
  144. data/lib/action_view/template/error.rb +101 -0
  145. data/lib/action_view/template/handler.rb +36 -0
  146. data/lib/action_view/template/handlers.rb +52 -0
  147. data/lib/action_view/template/handlers/builder.rb +17 -0
  148. data/lib/action_view/template/handlers/erb.rb +53 -0
  149. data/lib/action_view/template/handlers/rjs.rb +18 -0
  150. data/lib/action_view/template/resolver.rb +165 -0
  151. data/lib/action_view/template/template.rb +131 -0
  152. data/lib/action_view/template/text.rb +38 -0
  153. data/lib/action_view/test_case.rb +163 -0
  154. metadata +236 -0
@@ -0,0 +1,29 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml">
2
+ <head>
3
+ <title>Action Controller: Exception caught</title>
4
+ <style>
5
+ body { background-color: #fff; color: #333; }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a { color: #000; }
20
+ a:visited { color: #666; }
21
+ a:hover { color: #fff; background-color:#000; }
22
+ </style>
23
+ </head>
24
+ <body>
25
+
26
+ <%= yield %>
27
+
28
+ </body>
29
+ </html>
@@ -0,0 +1,2 @@
1
+ <h1>Template is missing</h1>
2
+ <p><%=h @exception.message %></p>
@@ -0,0 +1,10 @@
1
+ <h1>Routing Error</h1>
2
+ <p><pre><%=h @exception.message %></pre></p>
3
+ <% unless @exception.failures.empty? %><p>
4
+ <h2>Failure reasons:</h2>
5
+ <ol>
6
+ <% @exception.failures.each do |route, reason| %>
7
+ <li><code><%=h route.inspect.gsub('\\', '') %></code> failed because <%=h reason.downcase %></li>
8
+ <% end %>
9
+ </ol>
10
+ </p><% end %>
@@ -0,0 +1,21 @@
1
+ <h1>
2
+ <%=h @exception.original_exception.class.to_s %> in
3
+ <%=h @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%=h @request.parameters["action"] %>
4
+ </h1>
5
+
6
+ <p>
7
+ Showing <i><%=h @exception.file_name %></i> where line <b>#<%=h @exception.line_number %></b> raised:
8
+ <pre><code><%=h @exception.message %></code></pre>
9
+ </p>
10
+
11
+ <p>Extracted source (around line <b>#<%=h @exception.line_number %></b>):
12
+ <pre><code><%=h @exception.source_extract %></code></pre></p>
13
+
14
+ <p><%=h @exception.sub_template_message %></p>
15
+
16
+ <% @real_exception = @exception
17
+ @exception = @exception.original_exception || @exception %>
18
+ <%= render :file => "rescues/_trace.erb" %>
19
+ <% @exception = @real_exception %>
20
+
21
+ <%= render :file => "rescues/_request_and_response.erb" %>
@@ -0,0 +1,2 @@
1
+ <h1>Unknown action</h1>
2
+ <p><%=h @exception.message %></p>
@@ -0,0 +1,381 @@
1
+ require 'active_support/core_ext/object/to_param'
2
+ require 'active_support/core_ext/regexp'
3
+
4
+ module ActionDispatch
5
+ # == Routing
6
+ #
7
+ # The routing module provides URL rewriting in native Ruby. It's a way to
8
+ # redirect incoming requests to controllers and actions. This replaces
9
+ # mod_rewrite rules. Best of all, Rails' Routing works with any web server.
10
+ # Routes are defined in <tt>config/routes.rb</tt>.
11
+ #
12
+ # Consider the following route, installed by Rails when you generate your
13
+ # application:
14
+ #
15
+ # map.connect ':controller/:action/:id'
16
+ #
17
+ # This route states that it expects requests to consist of a
18
+ # <tt>:controller</tt> followed by an <tt>:action</tt> that in turn is fed
19
+ # some <tt>:id</tt>.
20
+ #
21
+ # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end up
22
+ # with:
23
+ #
24
+ # params = { :controller => 'blog',
25
+ # :action => 'edit',
26
+ # :id => '22'
27
+ # }
28
+ #
29
+ # Think of creating routes as drawing a map for your requests. The map tells
30
+ # them where to go based on some predefined pattern:
31
+ #
32
+ # ActionController::Routing::Routes.draw do |map|
33
+ # Pattern 1 tells some request to go to one place
34
+ # Pattern 2 tell them to go to another
35
+ # ...
36
+ # end
37
+ #
38
+ # The following symbols are special:
39
+ #
40
+ # :controller maps to your controller name
41
+ # :action maps to an action with your controllers
42
+ #
43
+ # Other names simply map to a parameter as in the case of <tt>:id</tt>.
44
+ #
45
+ # == Route priority
46
+ #
47
+ # Not all routes are created equally. Routes have priority defined by the
48
+ # order of appearance of the routes in the <tt>config/routes.rb</tt> file. The priority goes
49
+ # from top to bottom. The last route in that file is at the lowest priority
50
+ # and will be applied last. If no route matches, 404 is returned.
51
+ #
52
+ # Within blocks, the empty pattern is at the highest priority.
53
+ # In practice this works out nicely:
54
+ #
55
+ # ActionController::Routing::Routes.draw do |map|
56
+ # map.with_options :controller => 'blog' do |blog|
57
+ # blog.show '', :action => 'list'
58
+ # end
59
+ # map.connect ':controller/:action/:view'
60
+ # end
61
+ #
62
+ # In this case, invoking blog controller (with an URL like '/blog/')
63
+ # without parameters will activate the 'list' action by default.
64
+ #
65
+ # == Defaults routes and default parameters
66
+ #
67
+ # Setting a default route is straightforward in Rails - you simply append a
68
+ # Hash at the end of your mapping to set any default parameters.
69
+ #
70
+ # Example:
71
+ #
72
+ # ActionController::Routing:Routes.draw do |map|
73
+ # map.connect ':controller/:action/:id', :controller => 'blog'
74
+ # end
75
+ #
76
+ # This sets up +blog+ as the default controller if no other is specified.
77
+ # This means visiting '/' would invoke the blog controller.
78
+ #
79
+ # More formally, you can include arbitrary parameters in the route, thus:
80
+ #
81
+ # map.connect ':controller/:action/:id', :action => 'show', :page => 'Dashboard'
82
+ #
83
+ # This will pass the :page parameter to all incoming requests that match this route.
84
+ #
85
+ # Note: The default routes, as provided by the Rails generator, make all actions in every
86
+ # controller accessible via GET requests. You should consider removing them or commenting
87
+ # them out if you're using named routes and resources.
88
+ #
89
+ # == Named routes
90
+ #
91
+ # Routes can be named with the syntax <tt>map.name_of_route options</tt>,
92
+ # allowing for easy reference within your source as +name_of_route_url+
93
+ # for the full URL and +name_of_route_path+ for the URI path.
94
+ #
95
+ # Example:
96
+ #
97
+ # # In routes.rb
98
+ # map.login 'login', :controller => 'accounts', :action => 'login'
99
+ #
100
+ # # With render, redirect_to, tests, etc.
101
+ # redirect_to login_url
102
+ #
103
+ # Arguments can be passed as well.
104
+ #
105
+ # redirect_to show_item_path(:id => 25)
106
+ #
107
+ # Use <tt>map.root</tt> as a shorthand to name a route for the root path "".
108
+ #
109
+ # # In routes.rb
110
+ # map.root :controller => 'blogs'
111
+ #
112
+ # # would recognize http://www.example.com/ as
113
+ # params = { :controller => 'blogs', :action => 'index' }
114
+ #
115
+ # # and provide these named routes
116
+ # root_url # => 'http://www.example.com/'
117
+ # root_path # => ''
118
+ #
119
+ # You can also specify an already-defined named route in your <tt>map.root</tt> call:
120
+ #
121
+ # # In routes.rb
122
+ # map.new_session :controller => 'sessions', :action => 'new'
123
+ # map.root :new_session
124
+ #
125
+ # Note: when using +with_options+, the route is simply named after the
126
+ # method you call on the block parameter rather than map.
127
+ #
128
+ # # In routes.rb
129
+ # map.with_options :controller => 'blog' do |blog|
130
+ # blog.show '', :action => 'list'
131
+ # blog.delete 'delete/:id', :action => 'delete'
132
+ # blog.edit 'edit/:id', :action => 'edit'
133
+ # end
134
+ #
135
+ # # provides named routes for show, delete, and edit
136
+ # link_to @article.title, show_path(:id => @article.id)
137
+ #
138
+ # == Pretty URLs
139
+ #
140
+ # Routes can generate pretty URLs. For example:
141
+ #
142
+ # map.connect 'articles/:year/:month/:day',
143
+ # :controller => 'articles',
144
+ # :action => 'find_by_date',
145
+ # :year => /\d{4}/,
146
+ # :month => /\d{1,2}/,
147
+ # :day => /\d{1,2}/
148
+ #
149
+ # Using the route above, the URL "http://localhost:3000/articles/2005/11/06"
150
+ # maps to
151
+ #
152
+ # params = {:year => '2005', :month => '11', :day => '06'}
153
+ #
154
+ # == Regular Expressions and parameters
155
+ # You can specify a regular expression to define a format for a parameter.
156
+ #
157
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
158
+ # :action => 'show', :postalcode => /\d{5}(-\d{4})?/
159
+ #
160
+ # or, more formally:
161
+ #
162
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
163
+ # :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ }
164
+ #
165
+ # Formats can include the 'ignorecase' and 'extended syntax' regular
166
+ # expression modifiers:
167
+ #
168
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
169
+ # :action => 'show', :postalcode => /hx\d\d\s\d[a-z]{2}/i
170
+ #
171
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
172
+ # :action => 'show',:requirements => {
173
+ # :postalcode => /# Postcode format
174
+ # \d{5} #Prefix
175
+ # (-\d{4})? #Suffix
176
+ # /x
177
+ # }
178
+ #
179
+ # Using the multiline match modifier will raise an ArgumentError.
180
+ # Encoding regular expression modifiers are silently ignored. The
181
+ # match will always use the default encoding or ASCII.
182
+ #
183
+ # == Route globbing
184
+ #
185
+ # Specifying <tt>*[string]</tt> as part of a rule like:
186
+ #
187
+ # map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
188
+ #
189
+ # will glob all remaining parts of the route that were not recognized earlier.
190
+ # The globbed values are in <tt>params[:path]</tt> as an array of path segments.
191
+ #
192
+ # == Route conditions
193
+ #
194
+ # With conditions you can define restrictions on routes. Currently the only valid condition is <tt>:method</tt>.
195
+ #
196
+ # * <tt>:method</tt> - Allows you to specify which method can access the route. Possible values are <tt>:post</tt>,
197
+ # <tt>:get</tt>, <tt>:put</tt>, <tt>:delete</tt> and <tt>:any</tt>. The default value is <tt>:any</tt>,
198
+ # <tt>:any</tt> means that any method can access the route.
199
+ #
200
+ # Example:
201
+ #
202
+ # map.connect 'post/:id', :controller => 'posts', :action => 'show',
203
+ # :conditions => { :method => :get }
204
+ # map.connect 'post/:id', :controller => 'posts', :action => 'create_comment',
205
+ # :conditions => { :method => :post }
206
+ #
207
+ # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
208
+ # URL will route to the <tt>show</tt> action.
209
+ #
210
+ # == Reloading routes
211
+ #
212
+ # You can reload routes if you feel you must:
213
+ #
214
+ # ActionController::Routing::Routes.reload
215
+ #
216
+ # This will clear all named routes and reload routes.rb if the file has been modified from
217
+ # last load. To absolutely force reloading, use <tt>reload!</tt>.
218
+ #
219
+ # == Testing Routes
220
+ #
221
+ # The two main methods for testing your routes:
222
+ #
223
+ # === +assert_routing+
224
+ #
225
+ # def test_movie_route_properly_splits
226
+ # opts = {:controller => "plugin", :action => "checkout", :id => "2"}
227
+ # assert_routing "plugin/checkout/2", opts
228
+ # end
229
+ #
230
+ # +assert_routing+ lets you test whether or not the route properly resolves into options.
231
+ #
232
+ # === +assert_recognizes+
233
+ #
234
+ # def test_route_has_options
235
+ # opts = {:controller => "plugin", :action => "show", :id => "12"}
236
+ # assert_recognizes opts, "/plugins/show/12"
237
+ # end
238
+ #
239
+ # Note the subtle difference between the two: +assert_routing+ tests that
240
+ # a URL fits options while +assert_recognizes+ tests that a URL
241
+ # breaks into parameters properly.
242
+ #
243
+ # In tests you can simply pass the URL or named route to +get+ or +post+.
244
+ #
245
+ # def send_to_jail
246
+ # get '/jail'
247
+ # assert_response :success
248
+ # assert_template "jail/front"
249
+ # end
250
+ #
251
+ # def goes_to_login
252
+ # get login_url
253
+ # #...
254
+ # end
255
+ #
256
+ # == View a list of all your routes
257
+ #
258
+ # Run <tt>rake routes</tt>.
259
+ #
260
+ module Routing
261
+ autoload :DeprecatedMapper, 'action_dispatch/routing/deprecated_mapper'
262
+ autoload :Mapper, 'action_dispatch/routing/mapper'
263
+ autoload :Route, 'action_dispatch/routing/route'
264
+ autoload :RouteSet, 'action_dispatch/routing/route_set'
265
+
266
+ SEPARATORS = %w( / . ? )
267
+
268
+ HTTP_METHODS = [:get, :head, :post, :put, :delete, :options]
269
+
270
+ ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set
271
+
272
+ # The root paths which may contain controller files
273
+ mattr_accessor :controller_paths
274
+ self.controller_paths = []
275
+
276
+ # A helper module to hold URL related helpers.
277
+ module Helpers
278
+ include ActionController::PolymorphicRoutes
279
+ end
280
+
281
+ class << self
282
+ # Expects an array of controller names as the first argument.
283
+ # Executes the passed block with only the named controllers named available.
284
+ # This method is used in internal Rails testing.
285
+ def with_controllers(names)
286
+ prior_controllers = @possible_controllers
287
+ use_controllers! names
288
+ yield
289
+ ensure
290
+ use_controllers! prior_controllers
291
+ end
292
+
293
+ # Returns an array of paths, cleaned of double-slashes and relative path references.
294
+ # * "\\\" and "//" become "\\" or "/".
295
+ # * "/foo/bar/../config" becomes "/foo/config".
296
+ # The returned array is sorted by length, descending.
297
+ def normalize_paths(paths)
298
+ # do the hokey-pokey of path normalization...
299
+ paths = paths.collect do |path|
300
+ path = path.
301
+ gsub("//", "/"). # replace double / chars with a single
302
+ gsub("\\\\", "\\"). # replace double \ chars with a single
303
+ gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it
304
+
305
+ # eliminate .. paths where possible
306
+ re = %r{[^/\\]+[/\\]\.\.[/\\]}
307
+ path.gsub!(re, "") while path.match(re)
308
+ path
309
+ end
310
+
311
+ # start with longest path, first
312
+ paths = paths.uniq.sort_by { |path| - path.length }
313
+ end
314
+
315
+ # Returns the array of controller names currently available to ActionController::Routing.
316
+ def possible_controllers
317
+ unless @possible_controllers
318
+ @possible_controllers = []
319
+
320
+ paths = controller_paths.select { |path| File.directory?(path) && path != "." }
321
+
322
+ seen_paths = Hash.new {|h, k| h[k] = true; false}
323
+ normalize_paths(paths).each do |load_path|
324
+ Dir["#{load_path}/**/*_controller.rb"].collect do |path|
325
+ next if seen_paths[path.gsub(%r{^\.[/\\]}, "")]
326
+
327
+ controller_name = path[(load_path.length + 1)..-1]
328
+
329
+ controller_name.gsub!(/_controller\.rb\Z/, '')
330
+ @possible_controllers << controller_name
331
+ end
332
+ end
333
+
334
+ # remove duplicates
335
+ @possible_controllers.uniq!
336
+ end
337
+ @possible_controllers
338
+ end
339
+
340
+ # Replaces the internal list of controllers available to ActionController::Routing with the passed argument.
341
+ # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ])
342
+ def use_controllers!(controller_names)
343
+ @possible_controllers = controller_names
344
+ end
345
+
346
+ # Returns a controller path for a new +controller+ based on a +previous+ controller path.
347
+ # Handles 4 scenarios:
348
+ #
349
+ # * stay in the previous controller:
350
+ # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
351
+ #
352
+ # * stay in the previous namespace:
353
+ # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
354
+ #
355
+ # * forced move to the root namespace:
356
+ # controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
357
+ #
358
+ # * previous namespace is root:
359
+ # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
360
+ #
361
+ def controller_relative_to(controller, previous)
362
+ if controller.nil? then previous
363
+ elsif controller[0] == ?/ then controller[1..-1]
364
+ elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}"
365
+ else controller
366
+ end
367
+ end
368
+ end
369
+
370
+ ActiveSupport::Inflector.module_eval do
371
+ # Ensures that routes are reloaded when Rails inflections are updated.
372
+ def inflections_with_route_reloading(&block)
373
+ returning(inflections_without_route_reloading(&block)) {
374
+ ActionDispatch::Routing::Routes.reload! if block_given?
375
+ }
376
+ end
377
+
378
+ alias_method_chain :inflections, :route_reloading
379
+ end
380
+ end
381
+ end