actionpack 4.0.1 → 4.2.11.1

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 (241) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +402 -1173
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/lib/abstract_controller/base.rb +39 -7
  6. data/lib/abstract_controller/callbacks.rb +32 -53
  7. data/lib/abstract_controller/collector.rb +11 -1
  8. data/lib/abstract_controller/helpers.rb +26 -16
  9. data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
  10. data/lib/abstract_controller/rendering.rb +57 -127
  11. data/lib/abstract_controller/url_for.rb +1 -1
  12. data/lib/abstract_controller.rb +1 -2
  13. data/lib/action_controller/base.rb +19 -10
  14. data/lib/action_controller/caching/fragments.rb +7 -1
  15. data/lib/action_controller/caching.rb +2 -12
  16. data/lib/action_controller/log_subscriber.rb +29 -20
  17. data/lib/action_controller/metal/conditional_get.rb +37 -12
  18. data/lib/action_controller/metal/data_streaming.rb +1 -1
  19. data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
  20. data/lib/action_controller/metal/exceptions.rb +1 -1
  21. data/lib/action_controller/metal/flash.rb +17 -0
  22. data/lib/action_controller/metal/force_ssl.rb +2 -2
  23. data/lib/action_controller/metal/head.rb +8 -6
  24. data/lib/action_controller/metal/helpers.rb +6 -2
  25. data/lib/action_controller/metal/http_authentication.rb +45 -23
  26. data/lib/action_controller/metal/instrumentation.rb +9 -6
  27. data/lib/action_controller/metal/live.rb +173 -20
  28. data/lib/action_controller/metal/mime_responds.rb +127 -232
  29. data/lib/action_controller/metal/params_wrapper.rb +16 -9
  30. data/lib/action_controller/metal/rack_delegation.rb +1 -1
  31. data/lib/action_controller/metal/redirecting.rb +34 -26
  32. data/lib/action_controller/metal/renderers.rb +39 -12
  33. data/lib/action_controller/metal/rendering.rb +41 -14
  34. data/lib/action_controller/metal/request_forgery_protection.rb +147 -19
  35. data/lib/action_controller/metal/streaming.rb +19 -21
  36. data/lib/action_controller/metal/strong_parameters.rb +166 -22
  37. data/lib/action_controller/metal/testing.rb +0 -1
  38. data/lib/action_controller/metal/url_for.rb +11 -12
  39. data/lib/action_controller/metal.rb +14 -8
  40. data/lib/action_controller/model_naming.rb +1 -1
  41. data/lib/action_controller/railtie.rb +5 -1
  42. data/lib/action_controller/test_case.rb +160 -94
  43. data/lib/action_controller.rb +2 -18
  44. data/lib/action_dispatch/http/cache.rb +5 -4
  45. data/lib/action_dispatch/http/filter_parameters.rb +2 -2
  46. data/lib/action_dispatch/http/filter_redirect.rb +5 -4
  47. data/lib/action_dispatch/http/headers.rb +46 -10
  48. data/lib/action_dispatch/http/mime_negotiation.rb +31 -4
  49. data/lib/action_dispatch/http/mime_type.rb +25 -26
  50. data/lib/action_dispatch/http/mime_types.rb +1 -0
  51. data/lib/action_dispatch/http/parameter_filter.rb +1 -1
  52. data/lib/action_dispatch/http/parameters.rb +25 -41
  53. data/lib/action_dispatch/http/request.rb +49 -32
  54. data/lib/action_dispatch/http/response.rb +127 -25
  55. data/lib/action_dispatch/http/upload.rb +9 -21
  56. data/lib/action_dispatch/http/url.rb +97 -70
  57. data/lib/action_dispatch/journey/formatter.rb +35 -19
  58. data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
  59. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
  60. data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -33
  61. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  62. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  63. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
  64. data/lib/action_dispatch/journey/nodes/node.rb +4 -0
  65. data/lib/action_dispatch/journey/parser.rb +51 -59
  66. data/lib/action_dispatch/journey/parser.y +12 -10
  67. data/lib/action_dispatch/journey/path/pattern.rb +16 -19
  68. data/lib/action_dispatch/journey/route.rb +8 -19
  69. data/lib/action_dispatch/journey/router/strexp.rb +9 -6
  70. data/lib/action_dispatch/journey/router/utils.rb +54 -18
  71. data/lib/action_dispatch/journey/router.rb +53 -75
  72. data/lib/action_dispatch/journey/routes.rb +4 -0
  73. data/lib/action_dispatch/journey/scanner.rb +5 -5
  74. data/lib/action_dispatch/journey/visitors.rb +81 -60
  75. data/lib/action_dispatch/journey/visualizer/fsm.css +0 -4
  76. data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
  77. data/lib/action_dispatch/middleware/callbacks.rb +7 -7
  78. data/lib/action_dispatch/middleware/cookies.rb +119 -43
  79. data/lib/action_dispatch/middleware/debug_exceptions.rb +32 -13
  80. data/lib/action_dispatch/middleware/exception_wrapper.rb +60 -20
  81. data/lib/action_dispatch/middleware/flash.rb +37 -24
  82. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  83. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -3
  84. data/lib/action_dispatch/middleware/reloader.rb +11 -2
  85. data/lib/action_dispatch/middleware/remote_ip.rb +40 -54
  86. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +8 -7
  89. data/lib/action_dispatch/middleware/show_exceptions.rb +6 -2
  90. data/lib/action_dispatch/middleware/ssl.rb +10 -7
  91. data/lib/action_dispatch/middleware/static.rb +79 -23
  92. data/lib/action_dispatch/middleware/templates/rescues/{_request_and_response.erb → _request_and_response.html.erb} +0 -0
  93. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  94. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +21 -19
  95. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  96. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  97. data/lib/action_dispatch/middleware/templates/rescues/{diagnostics.erb → diagnostics.html.erb} +1 -1
  98. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  99. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  101. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  102. data/lib/action_dispatch/middleware/templates/rescues/{routing_error.erb → routing_error.html.erb} +3 -1
  103. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  104. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  106. data/lib/action_dispatch/middleware/templates/rescues/{unknown_action.erb → unknown_action.html.erb} +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  108. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +120 -64
  109. data/lib/action_dispatch/railtie.rb +5 -2
  110. data/lib/action_dispatch/request/session.rb +12 -0
  111. data/lib/action_dispatch/request/utils.rb +35 -0
  112. data/lib/action_dispatch/routing/endpoint.rb +10 -0
  113. data/lib/action_dispatch/routing/inspector.rb +11 -17
  114. data/lib/action_dispatch/routing/mapper.rb +519 -312
  115. data/lib/action_dispatch/routing/polymorphic_routes.rb +204 -79
  116. data/lib/action_dispatch/routing/redirection.rb +51 -26
  117. data/lib/action_dispatch/routing/route_set.rb +331 -206
  118. data/lib/action_dispatch/routing/routes_proxy.rb +5 -4
  119. data/lib/action_dispatch/routing/url_for.rb +19 -5
  120. data/lib/action_dispatch/routing.rb +9 -6
  121. data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
  122. data/lib/action_dispatch/testing/assertions/response.rb +9 -15
  123. data/lib/action_dispatch/testing/assertions/routing.rb +22 -22
  124. data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
  125. data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
  126. data/lib/action_dispatch/testing/assertions.rb +11 -7
  127. data/lib/action_dispatch/testing/integration.rb +31 -29
  128. data/lib/action_dispatch/testing/test_request.rb +1 -1
  129. data/lib/action_dispatch/testing/test_response.rb +1 -5
  130. data/lib/action_dispatch.rb +5 -8
  131. data/lib/action_pack/gem_version.rb +15 -0
  132. data/lib/action_pack/version.rb +4 -7
  133. data/lib/action_pack.rb +1 -1
  134. metadata +77 -159
  135. data/lib/abstract_controller/layouts.rb +0 -423
  136. data/lib/abstract_controller/view_paths.rb +0 -96
  137. data/lib/action_controller/deprecated/integration_test.rb +0 -5
  138. data/lib/action_controller/deprecated.rb +0 -7
  139. data/lib/action_controller/metal/responder.rb +0 -287
  140. data/lib/action_controller/record_identifier.rb +0 -31
  141. data/lib/action_controller/vendor/html-scanner.rb +0 -5
  142. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -24
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -7
  144. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -43
  145. data/lib/action_view/base.rb +0 -201
  146. data/lib/action_view/buffers.rb +0 -49
  147. data/lib/action_view/context.rb +0 -36
  148. data/lib/action_view/dependency_tracker.rb +0 -93
  149. data/lib/action_view/digestor.rb +0 -113
  150. data/lib/action_view/flows.rb +0 -76
  151. data/lib/action_view/helpers/active_model_helper.rb +0 -49
  152. data/lib/action_view/helpers/asset_tag_helper.rb +0 -320
  153. data/lib/action_view/helpers/asset_url_helper.rb +0 -355
  154. data/lib/action_view/helpers/atom_feed_helper.rb +0 -203
  155. data/lib/action_view/helpers/cache_helper.rb +0 -196
  156. data/lib/action_view/helpers/capture_helper.rb +0 -216
  157. data/lib/action_view/helpers/controller_helper.rb +0 -25
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -30
  159. data/lib/action_view/helpers/date_helper.rb +0 -1083
  160. data/lib/action_view/helpers/debug_helper.rb +0 -39
  161. data/lib/action_view/helpers/form_helper.rb +0 -1880
  162. data/lib/action_view/helpers/form_options_helper.rb +0 -838
  163. data/lib/action_view/helpers/form_tag_helper.rb +0 -785
  164. data/lib/action_view/helpers/javascript_helper.rb +0 -117
  165. data/lib/action_view/helpers/number_helper.rb +0 -441
  166. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  167. data/lib/action_view/helpers/record_tag_helper.rb +0 -106
  168. data/lib/action_view/helpers/rendering_helper.rb +0 -90
  169. data/lib/action_view/helpers/sanitize_helper.rb +0 -256
  170. data/lib/action_view/helpers/tag_helper.rb +0 -173
  171. data/lib/action_view/helpers/tags/base.rb +0 -148
  172. data/lib/action_view/helpers/tags/check_box.rb +0 -64
  173. data/lib/action_view/helpers/tags/checkable.rb +0 -16
  174. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -44
  175. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -84
  176. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -36
  177. data/lib/action_view/helpers/tags/collection_select.rb +0 -28
  178. data/lib/action_view/helpers/tags/color_field.rb +0 -25
  179. data/lib/action_view/helpers/tags/date_field.rb +0 -13
  180. data/lib/action_view/helpers/tags/date_select.rb +0 -72
  181. data/lib/action_view/helpers/tags/datetime_field.rb +0 -22
  182. data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -19
  183. data/lib/action_view/helpers/tags/datetime_select.rb +0 -8
  184. data/lib/action_view/helpers/tags/email_field.rb +0 -8
  185. data/lib/action_view/helpers/tags/file_field.rb +0 -8
  186. data/lib/action_view/helpers/tags/grouped_collection_select.rb +0 -29
  187. data/lib/action_view/helpers/tags/hidden_field.rb +0 -8
  188. data/lib/action_view/helpers/tags/label.rb +0 -66
  189. data/lib/action_view/helpers/tags/month_field.rb +0 -13
  190. data/lib/action_view/helpers/tags/number_field.rb +0 -18
  191. data/lib/action_view/helpers/tags/password_field.rb +0 -12
  192. data/lib/action_view/helpers/tags/radio_button.rb +0 -31
  193. data/lib/action_view/helpers/tags/range_field.rb +0 -8
  194. data/lib/action_view/helpers/tags/search_field.rb +0 -24
  195. data/lib/action_view/helpers/tags/select.rb +0 -40
  196. data/lib/action_view/helpers/tags/tel_field.rb +0 -8
  197. data/lib/action_view/helpers/tags/text_area.rb +0 -18
  198. data/lib/action_view/helpers/tags/text_field.rb +0 -29
  199. data/lib/action_view/helpers/tags/time_field.rb +0 -13
  200. data/lib/action_view/helpers/tags/time_select.rb +0 -8
  201. data/lib/action_view/helpers/tags/time_zone_select.rb +0 -20
  202. data/lib/action_view/helpers/tags/url_field.rb +0 -8
  203. data/lib/action_view/helpers/tags/week_field.rb +0 -13
  204. data/lib/action_view/helpers/tags.rb +0 -39
  205. data/lib/action_view/helpers/text_helper.rb +0 -443
  206. data/lib/action_view/helpers/translation_helper.rb +0 -107
  207. data/lib/action_view/helpers/url_helper.rb +0 -635
  208. data/lib/action_view/helpers.rb +0 -58
  209. data/lib/action_view/locale/en.yml +0 -56
  210. data/lib/action_view/log_subscriber.rb +0 -30
  211. data/lib/action_view/lookup_context.rb +0 -241
  212. data/lib/action_view/model_naming.rb +0 -12
  213. data/lib/action_view/path_set.rb +0 -77
  214. data/lib/action_view/railtie.rb +0 -43
  215. data/lib/action_view/record_identifier.rb +0 -84
  216. data/lib/action_view/renderer/abstract_renderer.rb +0 -47
  217. data/lib/action_view/renderer/partial_renderer.rb +0 -492
  218. data/lib/action_view/renderer/renderer.rb +0 -50
  219. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -103
  220. data/lib/action_view/renderer/template_renderer.rb +0 -96
  221. data/lib/action_view/routing_url_for.rb +0 -107
  222. data/lib/action_view/tasks/dependencies.rake +0 -17
  223. data/lib/action_view/template/error.rb +0 -138
  224. data/lib/action_view/template/handlers/builder.rb +0 -26
  225. data/lib/action_view/template/handlers/erb.rb +0 -146
  226. data/lib/action_view/template/handlers/raw.rb +0 -11
  227. data/lib/action_view/template/handlers.rb +0 -53
  228. data/lib/action_view/template/resolver.rb +0 -326
  229. data/lib/action_view/template/text.rb +0 -34
  230. data/lib/action_view/template/types.rb +0 -57
  231. data/lib/action_view/template.rb +0 -339
  232. data/lib/action_view/test_case.rb +0 -270
  233. data/lib/action_view/testing/resolvers.rb +0 -50
  234. data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
  235. data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
  236. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
  237. data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
  238. data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
  239. data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
  240. data/lib/action_view/vendor/html-scanner.rb +0 -20
  241. data/lib/action_view.rb +0 -93
@@ -74,6 +74,19 @@ module ActionDispatch
74
74
  # * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
75
75
  # Default is <tt>:url</tt>.
76
76
  #
77
+ # Also includes all the options from <tt>url_for</tt>. These include such
78
+ # things as <tt>:anchor</tt> or <tt>:trailing_slash</tt>. Example usage
79
+ # is given below:
80
+ #
81
+ # polymorphic_url([blog, post], anchor: 'my_anchor')
82
+ # # => "http://example.com/blogs/1/posts/1#my_anchor"
83
+ # polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app")
84
+ # # => "http://example.com/my_app/blogs/1/posts/1#my_anchor"
85
+ #
86
+ # For all of these options, see the documentation for <tt>url_for</tt>.
87
+ #
88
+ # ==== Functionality
89
+ #
77
90
  # # an Article record
78
91
  # polymorphic_url(record) # same as article_url(record)
79
92
  #
@@ -88,118 +101,230 @@ module ActionDispatch
88
101
  # polymorphic_url(Comment) # same as comments_url()
89
102
  #
90
103
  def polymorphic_url(record_or_hash_or_array, options = {})
91
- if record_or_hash_or_array.kind_of?(Array)
92
- record_or_hash_or_array = record_or_hash_or_array.compact
93
- if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
94
- proxy = record_or_hash_or_array.shift
95
- end
96
- record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
104
+ if Hash === record_or_hash_or_array
105
+ options = record_or_hash_or_array.merge(options)
106
+ record = options.delete :id
107
+ return polymorphic_url record, options
97
108
  end
98
109
 
99
- record = extract_record(record_or_hash_or_array)
100
- record = convert_to_model(record)
110
+ opts = options.dup
111
+ action = opts.delete :action
112
+ type = opts.delete(:routing_type) || :url
101
113
 
102
- args = Array === record_or_hash_or_array ?
103
- record_or_hash_or_array.dup :
104
- [ record_or_hash_or_array ]
105
-
106
- inflection = if options[:action] && options[:action].to_s == "new"
107
- args.pop
108
- :singular
109
- elsif (record.respond_to?(:persisted?) && !record.persisted?)
110
- args.pop
111
- :plural
112
- elsif record.is_a?(Class)
113
- args.pop
114
- :plural
115
- else
116
- :singular
117
- end
118
-
119
- args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
120
- named_route = build_named_route_call(record_or_hash_or_array, inflection, options)
121
-
122
- url_options = options.except(:action, :routing_type)
123
- unless url_options.empty?
124
- args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
125
- end
126
-
127
- args.collect! { |a| convert_to_model(a) }
128
-
129
- (proxy || self).send(named_route, *args)
114
+ HelperMethodBuilder.polymorphic_method self,
115
+ record_or_hash_or_array,
116
+ action,
117
+ type,
118
+ opts
130
119
  end
131
120
 
132
121
  # Returns the path component of a URL for the given record. It uses
133
122
  # <tt>polymorphic_url</tt> with <tt>routing_type: :path</tt>.
134
123
  def polymorphic_path(record_or_hash_or_array, options = {})
135
- polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path))
124
+ if Hash === record_or_hash_or_array
125
+ options = record_or_hash_or_array.merge(options)
126
+ record = options.delete :id
127
+ return polymorphic_path record, options
128
+ end
129
+
130
+ opts = options.dup
131
+ action = opts.delete :action
132
+ type = :path
133
+
134
+ HelperMethodBuilder.polymorphic_method self,
135
+ record_or_hash_or_array,
136
+ action,
137
+ type,
138
+ opts
136
139
  end
137
140
 
141
+
138
142
  %w(edit new).each do |action|
139
143
  module_eval <<-EOT, __FILE__, __LINE__ + 1
140
- def #{action}_polymorphic_url(record_or_hash, options = {}) # def edit_polymorphic_url(record_or_hash, options = {})
141
- polymorphic_url( # polymorphic_url(
142
- record_or_hash, # record_or_hash,
143
- options.merge(:action => "#{action}")) # options.merge(:action => "edit"))
144
- end # end
145
- #
146
- def #{action}_polymorphic_path(record_or_hash, options = {}) # def edit_polymorphic_path(record_or_hash, options = {})
147
- polymorphic_url( # polymorphic_url(
148
- record_or_hash, # record_or_hash,
149
- options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path))
150
- end # end
144
+ def #{action}_polymorphic_url(record_or_hash, options = {})
145
+ polymorphic_url_for_action("#{action}", record_or_hash, options)
146
+ end
147
+
148
+ def #{action}_polymorphic_path(record_or_hash, options = {})
149
+ polymorphic_path_for_action("#{action}", record_or_hash, options)
150
+ end
151
151
  EOT
152
152
  end
153
153
 
154
154
  private
155
- def action_prefix(options)
156
- options[:action] ? "#{options[:action]}_" : ''
155
+
156
+ def polymorphic_url_for_action(action, record_or_hash, options)
157
+ polymorphic_url(record_or_hash, options.merge(:action => action))
158
+ end
159
+
160
+ def polymorphic_path_for_action(action, record_or_hash, options)
161
+ polymorphic_path(record_or_hash, options.merge(:action => action))
162
+ end
163
+
164
+ class HelperMethodBuilder # :nodoc:
165
+ CACHE = { 'path' => {}, 'url' => {} }
166
+
167
+ def self.get(action, type)
168
+ type = type.to_s
169
+ CACHE[type].fetch(action) { build action, type }
157
170
  end
158
171
 
159
- def routing_type(options)
160
- options[:routing_type] || :url
172
+ def self.url; CACHE['url'.freeze][nil]; end
173
+ def self.path; CACHE['path'.freeze][nil]; end
174
+
175
+ def self.build(action, type)
176
+ prefix = action ? "#{action}_" : ""
177
+ suffix = type
178
+ if action.to_s == 'new'
179
+ HelperMethodBuilder.singular prefix, suffix
180
+ else
181
+ HelperMethodBuilder.plural prefix, suffix
182
+ end
161
183
  end
162
184
 
163
- def build_named_route_call(records, inflection, options = {})
164
- if records.is_a?(Array)
165
- record = records.pop
166
- route = records.map do |parent|
167
- if parent.is_a?(Symbol) || parent.is_a?(String)
168
- parent
169
- else
170
- model_name_from_record_or_class(parent).singular_route_key
171
- end
185
+ def self.singular(prefix, suffix)
186
+ new(->(name) { name.singular_route_key }, prefix, suffix)
187
+ end
188
+
189
+ def self.plural(prefix, suffix)
190
+ new(->(name) { name.route_key }, prefix, suffix)
191
+ end
192
+
193
+ def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
194
+ builder = get action, type
195
+
196
+ case record_or_hash_or_array
197
+ when Array
198
+ record_or_hash_or_array = record_or_hash_or_array.compact
199
+ if record_or_hash_or_array.empty?
200
+ raise ArgumentError, "Nil location provided. Can't build URI."
172
201
  end
202
+ if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
203
+ recipient = record_or_hash_or_array.shift
204
+ end
205
+
206
+ method, args = builder.handle_list record_or_hash_or_array
207
+ when String, Symbol
208
+ method, args = builder.handle_string record_or_hash_or_array
209
+ when Class
210
+ method, args = builder.handle_class record_or_hash_or_array
211
+
212
+ when nil
213
+ raise ArgumentError, "Nil location provided. Can't build URI."
173
214
  else
174
- record = extract_record(records)
175
- route = []
215
+ method, args = builder.handle_model record_or_hash_or_array
176
216
  end
177
217
 
178
- if record.is_a?(Symbol) || record.is_a?(String)
179
- route << record
180
- elsif record
181
- if inflection == :singular
182
- route << model_name_from_record_or_class(record).singular_route_key
218
+
219
+ if options.empty?
220
+ recipient.send(method, *args)
221
+ else
222
+ recipient.send(method, *args, options)
223
+ end
224
+ end
225
+
226
+ attr_reader :suffix, :prefix
227
+
228
+ def initialize(key_strategy, prefix, suffix)
229
+ @key_strategy = key_strategy
230
+ @prefix = prefix
231
+ @suffix = suffix
232
+ end
233
+
234
+ def handle_string(record)
235
+ [get_method_for_string(record), []]
236
+ end
237
+
238
+ def handle_string_call(target, str)
239
+ target.send get_method_for_string str
240
+ end
241
+
242
+ def handle_class(klass)
243
+ [get_method_for_class(klass), []]
244
+ end
245
+
246
+ def handle_class_call(target, klass)
247
+ target.send get_method_for_class klass
248
+ end
249
+
250
+ def handle_model(record)
251
+ args = []
252
+
253
+ model = record.to_model
254
+ name = if model.persisted?
255
+ args << model
256
+ model.model_name.singular_route_key
257
+ else
258
+ @key_strategy.call model.model_name
259
+ end
260
+
261
+ named_route = prefix + "#{name}_#{suffix}"
262
+
263
+ [named_route, args]
264
+ end
265
+
266
+ def handle_model_call(target, model)
267
+ method, args = handle_model model
268
+ target.send(method, *args)
269
+ end
270
+
271
+ def handle_list(list)
272
+ record_list = list.dup
273
+ record = record_list.pop
274
+
275
+ args = []
276
+
277
+ route = record_list.map { |parent|
278
+ case parent
279
+ when Symbol, String
280
+ parent.to_s
281
+ when Class
282
+ args << parent
283
+ parent.model_name.singular_route_key
183
284
  else
184
- route << model_name_from_record_or_class(record).route_key
285
+ args << parent.to_model
286
+ parent.to_model.model_name.singular_route_key
185
287
  end
288
+ }
289
+
290
+ route <<
291
+ case record
292
+ when Symbol, String
293
+ record.to_s
294
+ when Class
295
+ @key_strategy.call record.model_name
186
296
  else
187
- raise ArgumentError, "Nil location provided. Can't build URI."
297
+ model = record.to_model
298
+ if model.persisted?
299
+ args << model
300
+ model.model_name.singular_route_key
301
+ else
302
+ @key_strategy.call model.model_name
303
+ end
188
304
  end
189
305
 
190
- route << routing_type(options)
306
+ route << suffix
191
307
 
192
- action_prefix(options) + route.join("_")
308
+ named_route = prefix + route.join("_")
309
+ [named_route, args]
193
310
  end
194
311
 
195
- def extract_record(record_or_hash_or_array)
196
- case record_or_hash_or_array
197
- when Array; record_or_hash_or_array.last
198
- when Hash; record_or_hash_or_array[:id]
199
- else record_or_hash_or_array
200
- end
312
+ private
313
+
314
+ def get_method_for_class(klass)
315
+ name = @key_strategy.call klass.model_name
316
+ prefix + "#{name}_#{suffix}"
317
+ end
318
+
319
+ def get_method_for_string(str)
320
+ prefix + "#{str}_#{suffix}"
201
321
  end
322
+
323
+ [nil, 'new', 'edit'].each do |action|
324
+ CACHE['url'][action] = build action, 'url'
325
+ CACHE['path'][action] = build action, 'path'
326
+ end
327
+ end
202
328
  end
203
329
  end
204
330
  end
205
-
@@ -3,10 +3,11 @@ require 'active_support/core_ext/uri'
3
3
  require 'active_support/core_ext/array/extract_options'
4
4
  require 'rack/utils'
5
5
  require 'action_controller/metal/exceptions'
6
+ require 'action_dispatch/routing/endpoint'
6
7
 
7
8
  module ActionDispatch
8
9
  module Routing
9
- class Redirect # :nodoc:
10
+ class Redirect < Endpoint # :nodoc:
10
11
  attr_reader :status, :block
11
12
 
12
13
  def initialize(status, block)
@@ -14,27 +15,29 @@ module ActionDispatch
14
15
  @block = block
15
16
  end
16
17
 
18
+ def redirect?; true; end
19
+
17
20
  def call(env)
18
- req = Request.new(env)
21
+ serve Request.new env
22
+ end
19
23
 
20
- # If any of the path parameters has a invalid encoding then
21
- # raise since it's likely to trigger errors further on.
22
- req.symbolized_path_parameters.each do |key, value|
23
- unless value.valid_encoding?
24
- raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
24
+ def serve(req)
25
+ req.check_path_parameters!
26
+ uri = URI.parse(path(req.path_parameters, req))
27
+
28
+ unless uri.host
29
+ if relative_path?(uri.path)
30
+ uri.path = "#{req.script_name}/#{uri.path}"
31
+ elsif uri.path.empty?
32
+ uri.path = req.script_name.empty? ? "/" : req.script_name
25
33
  end
26
34
  end
27
-
28
- uri = URI.parse(path(req.symbolized_path_parameters, req))
35
+
29
36
  uri.scheme ||= req.scheme
30
37
  uri.host ||= req.host
31
38
  uri.port ||= req.port unless req.standard_port?
32
39
 
33
- if relative_path?(uri.path)
34
- uri.path = "#{req.script_name}/#{uri.path}"
35
- end
36
-
37
- body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>)
40
+ body = %(<html><body>You are being <a href="#{ERB::Util.unwrapped_html_escape(uri.to_s)}">redirected</a>.</body></html>)
38
41
 
39
42
  headers = {
40
43
  'Location' => uri.to_s,
@@ -57,11 +60,33 @@ module ActionDispatch
57
60
  def relative_path?(path)
58
61
  path && !path.empty? && path[0] != '/'
59
62
  end
63
+
64
+ def escape(params)
65
+ Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
66
+ end
67
+
68
+ def escape_fragment(params)
69
+ Hash[params.map{ |k,v| [k, Journey::Router::Utils.escape_fragment(v)] }]
70
+ end
71
+
72
+ def escape_path(params)
73
+ Hash[params.map{ |k,v| [k, Journey::Router::Utils.escape_path(v)] }]
74
+ end
60
75
  end
61
76
 
62
77
  class PathRedirect < Redirect
78
+ URL_PARTS = /\A([^?]+)?(\?[^#]+)?(#.+)?\z/
79
+
63
80
  def path(params, request)
64
- (params.empty? || !block.match(/%\{\w*\}/)) ? block : (block % escape(params))
81
+ if block.match(URL_PARTS)
82
+ path = interpolation_required?($1, params) ? $1 % escape_path(params) : $1
83
+ query = interpolation_required?($2, params) ? $2 % escape(params) : $2
84
+ fragment = interpolation_required?($3, params) ? $3 % escape_fragment(params) : $3
85
+
86
+ "#{path}#{query}#{fragment}"
87
+ else
88
+ interpolation_required?(block, params) ? block % escape(params) : block
89
+ end
65
90
  end
66
91
 
67
92
  def inspect
@@ -69,8 +94,8 @@ module ActionDispatch
69
94
  end
70
95
 
71
96
  private
72
- def escape(params)
73
- Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
97
+ def interpolation_required?(string, params)
98
+ !params.empty? && string && string.match(/%\{\w*\}/)
74
99
  end
75
100
  end
76
101
 
@@ -90,22 +115,22 @@ module ActionDispatch
90
115
  url_options[:path] = (url_options[:path] % escape_path(params))
91
116
  end
92
117
 
93
- if relative_path?(url_options[:path])
94
- url_options[:path] = "/#{url_options[:path]}"
95
- url_options[:script_name] = request.script_name
118
+ unless options[:host] || options[:domain]
119
+ if relative_path?(url_options[:path])
120
+ url_options[:path] = "/#{url_options[:path]}"
121
+ url_options[:script_name] = request.script_name
122
+ elsif url_options[:path].empty?
123
+ url_options[:path] = request.script_name.empty? ? "/" : ""
124
+ url_options[:script_name] = request.script_name
125
+ end
96
126
  end
97
-
127
+
98
128
  ActionDispatch::Http::URL.url_for url_options
99
129
  end
100
130
 
101
131
  def inspect
102
132
  "redirect(#{status}, #{options.map{ |k,v| "#{k}: #{v}" }.join(', ')})"
103
133
  end
104
-
105
- private
106
- def escape_path(params)
107
- Hash[params.map{ |k,v| [k, URI.parser.escape(v)] }]
108
- end
109
134
  end
110
135
 
111
136
  module Redirection