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
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 1233f96f807c0dc8b447b84b7b7d031267147203
4
- data.tar.gz: d1a329c22c422cf76385feda31f9200f4afe1b10
5
- SHA512:
6
- metadata.gz: c9a95139477e0cfa773bb32f27e18588d79580402313f865f5193a308c8d422dced7e957e4e46422501f7020d5a957ec0f5996a910b7f240314353b82fbbc462
7
- data.tar.gz: 232a6d69810531cb7496203f04a304f6b9cab4c5180bf2c34ddfc29775d375dae3e5d7da3782497888692aaf007fdf1aac8e0e42885f68cbc875e4d5e615adbf
@@ -1,143 +0,0 @@
1
- module ActionController
2
- class Base
3
- # Deprecated methods. Wrap them in a module so they can be overwritten by plugins
4
- # (like the verify method.)
5
- module DeprecatedBehavior #:nodoc:
6
- def relative_url_root
7
- ActiveSupport::Deprecation.warn "ActionController::Base.relative_url_root is ineffective. " <<
8
- "Please stop using it.", caller
9
- end
10
-
11
- def relative_url_root=(value)
12
- ActiveSupport::Deprecation.warn "ActionController::Base.relative_url_root= is ineffective. " <<
13
- "Please stop using it.", caller
14
- end
15
-
16
- def consider_all_requests_local
17
- ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local is deprecated, " <<
18
- "use Rails.application.config.consider_all_requests_local instead", caller
19
- Rails.application.config.consider_all_requests_local
20
- end
21
-
22
- def consider_all_requests_local=(value)
23
- ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local= is deprecated. " <<
24
- "Please configure it on your application with config.consider_all_requests_local=", caller
25
- Rails.application.config.consider_all_requests_local = value
26
- end
27
-
28
- def allow_concurrency
29
- ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency is deprecated, " <<
30
- "use Rails.application.config.allow_concurrency instead", caller
31
- Rails.application.config.allow_concurrency
32
- end
33
-
34
- def allow_concurrency=(value)
35
- ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency= is deprecated. " <<
36
- "Please configure it on your application with config.allow_concurrency=", caller
37
- Rails.application.config.allow_concurrency = value
38
- end
39
-
40
- def ip_spoofing_check=(value)
41
- ActiveSupport::Deprecation.warn "ActionController::Base.ip_spoofing_check= is deprecated. " <<
42
- "Please configure it on your application with config.action_dispatch.ip_spoofing_check=", caller
43
- Rails.application.config.action_dispatch.ip_spoofing_check = value
44
- end
45
-
46
- def ip_spoofing_check
47
- ActiveSupport::Deprecation.warn "ActionController::Base.ip_spoofing_check is deprecated. " <<
48
- "Configuring ip_spoofing_check on the application configures a middleware.", caller
49
- Rails.application.config.action_dispatch.ip_spoofing_check
50
- end
51
-
52
- def cookie_verifier_secret=(value)
53
- ActiveSupport::Deprecation.warn "ActionController::Base.cookie_verifier_secret= is deprecated. " <<
54
- "Please configure it on your application with config.secret_token=", caller
55
- end
56
-
57
- def cookie_verifier_secret
58
- ActiveSupport::Deprecation.warn "ActionController::Base.cookie_verifier_secret is deprecated.", caller
59
- end
60
-
61
- def trusted_proxies=(value)
62
- ActiveSupport::Deprecation.warn "ActionController::Base.trusted_proxies= is deprecated. " <<
63
- "Please configure it on your application with config.action_dispatch.trusted_proxies=", caller
64
- Rails.application.config.action_dispatch.ip_spoofing_check = value
65
- end
66
-
67
- def trusted_proxies
68
- ActiveSupport::Deprecation.warn "ActionController::Base.trusted_proxies is deprecated. " <<
69
- "Configuring trusted_proxies on the application configures a middleware.", caller
70
- Rails.application.config.action_dispatch.ip_spoofing_check = value
71
- end
72
-
73
- def session(*args)
74
- ActiveSupport::Deprecation.warn(
75
- "Disabling sessions for a single controller has been deprecated. " +
76
- "Sessions are now lazy loaded. So if you don't access them, " +
77
- "consider them off. You can still modify the session cookie " +
78
- "options with request.session_options.", caller)
79
- end
80
-
81
- def session=(value)
82
- ActiveSupport::Deprecation.warn "ActionController::Base.session= is deprecated. " <<
83
- "Please configure it on your application with config.session_store :cookie_store, :key => '....'", caller
84
-
85
- if secret = value.delete(:secret)
86
- Rails.application.config.secret_token = secret
87
- end
88
-
89
- if value.delete(:disabled)
90
- Rails.application.config.session_store :disabled
91
- else
92
- store = Rails.application.config.session_store
93
- Rails.application.config.session_store store, value
94
- end
95
- end
96
-
97
- # Controls the resource action separator
98
- def resource_action_separator
99
- @resource_action_separator ||= "/"
100
- end
101
-
102
- def resource_action_separator=(val)
103
- ActiveSupport::Deprecation.warn "ActionController::Base.resource_action_separator is deprecated and only " \
104
- "works with the deprecated router DSL."
105
- @resource_action_separator = val
106
- end
107
-
108
- def use_accept_header
109
- ActiveSupport::Deprecation.warn "ActionController::Base.use_accept_header doesn't do anything anymore. " \
110
- "The accept header is always taken into account."
111
- end
112
-
113
- def use_accept_header=(val)
114
- use_accept_header
115
- end
116
-
117
- # This method has been moved to ActionDispatch::Request.filter_parameters
118
- def filter_parameter_logging(*args, &block)
119
- ActiveSupport::Deprecation.warn("Setting filter_parameter_logging in ActionController is deprecated and has no longer effect, please set 'config.filter_parameters' in config/application.rb instead", caller)
120
- filter = Rails.application.config.filter_parameters
121
- filter.concat(args)
122
- filter << block if block
123
- filter
124
- end
125
-
126
- # This was moved to a plugin
127
- def verify(*args)
128
- ActiveSupport::Deprecation.warn "verify was removed from Rails and is now available as a plugin. " \
129
- "Please install it with `rails plugin install git://github.com/sikachu/verification.git`.", caller
130
- end
131
-
132
- def exempt_from_layout(*)
133
- ActiveSupport::Deprecation.warn "exempt_from_layout is no longer needed, because layouts in Rails 3 " \
134
- "are restricted to the content-type of the template that was rendered.", caller
135
- end
136
- end
137
-
138
- extend DeprecatedBehavior
139
-
140
- delegate :consider_all_requests_local, :consider_all_requests_local=,
141
- :allow_concurrency, :allow_concurrency=, :to => :"self.class"
142
- end
143
- end
@@ -1,28 +0,0 @@
1
- module ActionController
2
- class Dispatcher
3
- class << self
4
- def before_dispatch(*args, &block)
5
- ActiveSupport::Deprecation.warn "ActionController::Dispatcher.before_dispatch is deprecated. " <<
6
- "Please use ActionDispatch::Callbacks.before instead.", caller
7
- ActionDispatch::Callbacks.before(*args, &block)
8
- end
9
-
10
- def after_dispatch(*args, &block)
11
- ActiveSupport::Deprecation.warn "ActionController::Dispatcher.after_dispatch is deprecated. " <<
12
- "Please use ActionDispatch::Callbacks.after instead.", caller
13
- ActionDispatch::Callbacks.after(*args, &block)
14
- end
15
-
16
- def to_prepare(*args, &block)
17
- ActiveSupport::Deprecation.warn "ActionController::Dispatcher.to_prepare is deprecated. " <<
18
- "Please use config.to_prepare instead", caller
19
- ActionDispatch::Callbacks.after(*args, &block)
20
- end
21
-
22
- def new
23
- ActiveSupport::Deprecation.warn "ActionController::Dispatcher.new is deprecated, use Rails.application instead."
24
- Rails.application
25
- end
26
- end
27
- end
28
- end
@@ -1,14 +0,0 @@
1
- module ActionController
2
- module UrlWriter
3
- def self.included(klass)
4
- ActiveSupport::Deprecation.warn "include ActionController::UrlWriter is deprecated. Instead, " \
5
- "include Rails.application.routes.url_helpers"
6
- klass.class_eval { include Rails.application.routes.url_helpers }
7
- end
8
- end
9
-
10
- class UrlRewriter
11
- def initialize(*)
12
- end
13
- end
14
- end
@@ -1,525 +0,0 @@
1
- require 'active_support/core_ext/object/blank'
2
- require 'active_support/core_ext/object/with_options'
3
- require 'active_support/core_ext/object/try'
4
-
5
- module ActionDispatch
6
- module Routing
7
- class RouteSet
8
- attr_accessor :controller_namespaces
9
-
10
- CONTROLLER_REGEXP = /[_a-zA-Z0-9]+/
11
-
12
- def controller_constraints
13
- @controller_constraints ||= begin
14
- namespaces = controller_namespaces + in_memory_controller_namespaces
15
- source = namespaces.map { |ns| "#{Regexp.escape(ns)}/#{CONTROLLER_REGEXP.source}" }
16
- source << CONTROLLER_REGEXP.source
17
- Regexp.compile(source.sort.reverse.join('|'))
18
- end
19
- end
20
-
21
- def in_memory_controller_namespaces
22
- namespaces = Set.new
23
- ActionController::Base.descendants.each do |klass|
24
- next if klass.anonymous?
25
- namespaces << klass.name.underscore.split('/')[0...-1].join('/')
26
- end
27
- namespaces.delete('')
28
- namespaces
29
- end
30
- end
31
-
32
- class DeprecatedMapper #:nodoc:
33
- def initialize(set) #:nodoc:
34
- ActiveSupport::Deprecation.warn "You are using the old router DSL which will be removed in Rails 3.1. " <<
35
- "Please check how to update your routes file at: http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/"
36
- @set = set
37
- end
38
-
39
- def connect(path, options = {})
40
- options = options.dup
41
-
42
- if conditions = options.delete(:conditions)
43
- conditions = conditions.dup
44
- method = [conditions.delete(:method)].flatten.compact
45
- method.map! { |m|
46
- m = m.to_s.upcase
47
-
48
- if m == "HEAD"
49
- raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
50
- end
51
-
52
- unless HTTP_METHODS.include?(m.downcase.to_sym)
53
- raise ArgumentError, "Invalid HTTP method specified in route conditions"
54
- end
55
-
56
- m
57
- }
58
-
59
- if method.length > 1
60
- method = Regexp.union(*method)
61
- elsif method.length == 1
62
- method = method.first
63
- else
64
- method = nil
65
- end
66
- end
67
-
68
- path_prefix = options.delete(:path_prefix)
69
- name_prefix = options.delete(:name_prefix)
70
- namespace = options.delete(:namespace)
71
-
72
- name = options.delete(:_name)
73
- name = "#{name_prefix}#{name}" if name_prefix
74
-
75
- requirements = options.delete(:requirements) || {}
76
- defaults = options.delete(:defaults) || {}
77
- options.each do |k, v|
78
- if v.is_a?(Regexp)
79
- if value = options.delete(k)
80
- requirements[k.to_sym] = value
81
- end
82
- else
83
- value = options.delete(k)
84
- defaults[k.to_sym] = value.is_a?(Symbol) ? value : value.to_param
85
- end
86
- end
87
-
88
- requirements.each do |_, requirement|
89
- if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
90
- raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
91
- end
92
- if requirement.multiline?
93
- raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
94
- end
95
- end
96
-
97
- requirements[:controller] ||= @set.controller_constraints
98
-
99
- if defaults[:controller]
100
- defaults[:action] ||= 'index'
101
- defaults[:controller] = defaults[:controller].to_s
102
- defaults[:controller] = "#{namespace}#{defaults[:controller]}" if namespace
103
- end
104
-
105
- if defaults[:action]
106
- defaults[:action] = defaults[:action].to_s
107
- end
108
-
109
- if path.is_a?(String)
110
- path = "#{path_prefix}/#{path}" if path_prefix
111
- path = path.gsub('.:format', '(.:format)')
112
- path = optionalize_trailing_dynamic_segments(path, requirements, defaults)
113
- glob = $1.to_sym if path =~ /\/\*(\w+)$/
114
- path = ::Rack::Mount::Utils.normalize_path(path)
115
-
116
- if glob && !defaults[glob].blank?
117
- raise ActionController::RoutingError, "paths cannot have non-empty default values"
118
- end
119
- end
120
-
121
- app = Routing::RouteSet::Dispatcher.new(:defaults => defaults, :glob => glob)
122
-
123
- conditions = {}
124
- conditions[:request_method] = method if method
125
- conditions[:path_info] = path if path
126
-
127
- @set.add_route(app, conditions, requirements, defaults, name)
128
- end
129
-
130
- def optionalize_trailing_dynamic_segments(path, requirements, defaults) #:nodoc:
131
- path = (path =~ /^\//) ? path.dup : "/#{path}"
132
- optional, segments = true, []
133
-
134
- required_segments = requirements.keys
135
- required_segments -= defaults.keys.compact
136
-
137
- old_segments = path.split('/')
138
- old_segments.shift
139
- length = old_segments.length
140
-
141
- old_segments.reverse.each_with_index do |segment, index|
142
- required_segments.each do |required|
143
- if segment =~ /#{required}/
144
- optional = false
145
- break
146
- end
147
- end
148
-
149
- if optional
150
- if segment == ":id" && segments.include?(":action")
151
- optional = false
152
- elsif segment == ":controller" || segment == ":action" || segment == ":id"
153
- # Ignore
154
- elsif !(segment =~ /^:\w+$/) &&
155
- !(segment =~ /^:\w+\(\.:format\)$/)
156
- optional = false
157
- elsif segment =~ /^:(\w+)$/
158
- if defaults.has_key?($1.to_sym)
159
- defaults.delete($1.to_sym) if defaults[$1.to_sym].nil?
160
- else
161
- optional = false
162
- end
163
- end
164
- end
165
-
166
- if optional && index < length - 1
167
- segments.unshift('(/', segment)
168
- segments.push(')')
169
- elsif optional
170
- segments.unshift('/(', segment)
171
- segments.push(')')
172
- else
173
- segments.unshift('/', segment)
174
- end
175
- end
176
-
177
- segments.join
178
- end
179
- private :optionalize_trailing_dynamic_segments
180
-
181
- # Creates a named route called "root" for matching the root level request.
182
- def root(options = {})
183
- if options.is_a?(Symbol)
184
- if source_route = @set.named_routes.routes[options]
185
- options = source_route.defaults.merge({ :conditions => source_route.conditions })
186
- end
187
- end
188
- named_route("root", '', options)
189
- end
190
-
191
- def named_route(name, path, options = {}) #:nodoc:
192
- options[:_name] = name
193
- connect(path, options)
194
- end
195
-
196
- def namespace(name, options = {}, &block)
197
- if options[:namespace]
198
- with_options({:path_prefix => "#{options.delete(:path_prefix)}/#{name}", :name_prefix => "#{options.delete(:name_prefix)}#{name}_", :namespace => "#{options.delete(:namespace)}#{name}/" }.merge(options), &block)
199
- else
200
- with_options({:path_prefix => name, :name_prefix => "#{name}_", :namespace => "#{name}/" }.merge(options), &block)
201
- end
202
- end
203
-
204
- def method_missing(route_name, *args, &proc) #:nodoc:
205
- super unless args.length >= 1 && proc.nil?
206
- named_route(route_name, *args)
207
- end
208
-
209
- INHERITABLE_OPTIONS = :namespace, :shallow
210
-
211
- class Resource #:nodoc:
212
- DEFAULT_ACTIONS = :index, :create, :new, :edit, :show, :update, :destroy
213
-
214
- attr_reader :collection_methods, :member_methods, :new_methods
215
- attr_reader :path_prefix, :name_prefix, :path_segment
216
- attr_reader :plural, :singular
217
- attr_reader :options, :defaults
218
-
219
- def initialize(entities, options, defaults)
220
- @plural ||= entities
221
- @singular ||= options[:singular] || plural.to_s.singularize
222
- @path_segment = options.delete(:as) || @plural
223
-
224
- @options = options
225
- @defaults = defaults
226
-
227
- arrange_actions
228
- add_default_actions
229
- set_allowed_actions
230
- set_prefixes
231
- end
232
-
233
- def controller
234
- @controller ||= "#{options[:namespace]}#{(options[:controller] || plural).to_s}"
235
- end
236
-
237
- def requirements(with_id = false)
238
- @requirements ||= @options[:requirements] || {}
239
- @id_requirement ||= { :id => @requirements.delete(:id) || /[^#{Routing::SEPARATORS.join}]+/ }
240
-
241
- with_id ? @requirements.merge(@id_requirement) : @requirements
242
- end
243
-
244
- def conditions
245
- @conditions ||= @options[:conditions] || {}
246
- end
247
-
248
- def path
249
- @path ||= "#{path_prefix}/#{path_segment}"
250
- end
251
-
252
- def new_path
253
- new_action = self.options[:path_names][:new] if self.options[:path_names]
254
- new_action ||= self.defaults[:path_names][:new]
255
- @new_path ||= "#{path}/#{new_action}"
256
- end
257
-
258
- def shallow_path_prefix
259
- @shallow_path_prefix ||= @options[:shallow] ? @options[:namespace].try(:sub, /\/$/, '') : path_prefix
260
- end
261
-
262
- def member_path
263
- @member_path ||= "#{shallow_path_prefix}/#{path_segment}/:id"
264
- end
265
-
266
- def nesting_path_prefix
267
- @nesting_path_prefix ||= "#{shallow_path_prefix}/#{path_segment}/:#{singular}_id"
268
- end
269
-
270
- def shallow_name_prefix
271
- @shallow_name_prefix ||= @options[:shallow] ? @options[:namespace].try(:gsub, /\//, '_') : name_prefix
272
- end
273
-
274
- def nesting_name_prefix
275
- "#{shallow_name_prefix}#{singular}_"
276
- end
277
-
278
- def action_separator
279
- @action_separator ||= ActionController::Base.resource_action_separator
280
- end
281
-
282
- def uncountable?
283
- @singular.to_s == @plural.to_s
284
- end
285
-
286
- def has_action?(action)
287
- !DEFAULT_ACTIONS.include?(action) || action_allowed?(action)
288
- end
289
-
290
- protected
291
- def arrange_actions
292
- @collection_methods = arrange_actions_by_methods(options.delete(:collection))
293
- @member_methods = arrange_actions_by_methods(options.delete(:member))
294
- @new_methods = arrange_actions_by_methods(options.delete(:new))
295
- end
296
-
297
- def add_default_actions
298
- add_default_action(member_methods, :get, :edit)
299
- add_default_action(new_methods, :get, :new)
300
- end
301
-
302
- def set_allowed_actions
303
- only, except = @options.values_at(:only, :except)
304
- @allowed_actions ||= {}
305
-
306
- if only == :all || except == :none
307
- only = nil
308
- except = []
309
- elsif only == :none || except == :all
310
- only = []
311
- except = nil
312
- end
313
-
314
- if only
315
- @allowed_actions[:only] = Array(only).map {|a| a.to_sym }
316
- elsif except
317
- @allowed_actions[:except] = Array(except).map {|a| a.to_sym }
318
- end
319
- end
320
-
321
- def action_allowed?(action)
322
- only, except = @allowed_actions.values_at(:only, :except)
323
- (!only || only.include?(action)) && (!except || !except.include?(action))
324
- end
325
-
326
- def set_prefixes
327
- @path_prefix = options.delete(:path_prefix)
328
- @name_prefix = options.delete(:name_prefix)
329
- end
330
-
331
- def arrange_actions_by_methods(actions)
332
- (actions || {}).inject({}) do |flipped_hash, (key, value)|
333
- (flipped_hash[value] ||= []) << key
334
- flipped_hash
335
- end
336
- end
337
-
338
- def add_default_action(collection, method, action)
339
- (collection[method] ||= []).unshift(action)
340
- end
341
- end
342
-
343
- class SingletonResource < Resource #:nodoc:
344
- def initialize(entity, options, defaults)
345
- @singular = @plural = entity
346
- options[:controller] ||= @singular.to_s.pluralize
347
- super
348
- end
349
-
350
- alias_method :shallow_path_prefix, :path_prefix
351
- alias_method :shallow_name_prefix, :name_prefix
352
- alias_method :member_path, :path
353
- alias_method :nesting_path_prefix, :path
354
- end
355
-
356
- def resources(*entities, &block)
357
- options = entities.extract_options!
358
- entities.each { |entity| map_resource(entity, options.dup, &block) }
359
- end
360
-
361
- def resource(*entities, &block)
362
- options = entities.extract_options!
363
- entities.each { |entity| map_singleton_resource(entity, options.dup, &block) }
364
- end
365
-
366
- private
367
- def map_resource(entities, options = {}, &block)
368
- resource = Resource.new(entities, options, :path_names => @set.resources_path_names)
369
-
370
- with_options :controller => resource.controller do |map|
371
- map_associations(resource, options)
372
-
373
- if block_given?
374
- with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
375
- end
376
-
377
- map_collection_actions(map, resource)
378
- map_default_collection_actions(map, resource)
379
- map_new_actions(map, resource)
380
- map_member_actions(map, resource)
381
- end
382
- end
383
-
384
- def map_singleton_resource(entities, options = {}, &block)
385
- resource = SingletonResource.new(entities, options, :path_names => @set.resources_path_names)
386
-
387
- with_options :controller => resource.controller do |map|
388
- map_associations(resource, options)
389
-
390
- if block_given?
391
- with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
392
- end
393
-
394
- map_collection_actions(map, resource)
395
- map_new_actions(map, resource)
396
- map_member_actions(map, resource)
397
- map_default_singleton_actions(map, resource)
398
- end
399
- end
400
-
401
- def map_associations(resource, options)
402
- map_has_many_associations(resource, options.delete(:has_many), options) if options[:has_many]
403
-
404
- path_prefix = "#{options.delete(:path_prefix)}#{resource.nesting_path_prefix}"
405
- name_prefix = "#{options.delete(:name_prefix)}#{resource.nesting_name_prefix}"
406
-
407
- Array(options[:has_one]).each do |association|
408
- resource(association, options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => path_prefix, :name_prefix => name_prefix))
409
- end
410
- end
411
-
412
- def map_has_many_associations(resource, associations, options)
413
- case associations
414
- when Hash
415
- associations.each do |association,has_many|
416
- map_has_many_associations(resource, association, options.merge(:has_many => has_many))
417
- end
418
- when Array
419
- associations.each do |association|
420
- map_has_many_associations(resource, association, options)
421
- end
422
- when Symbol, String
423
- resources(associations, options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :has_many => options[:has_many]))
424
- else
425
- end
426
- end
427
-
428
- def map_collection_actions(map, resource)
429
- resource.collection_methods.each do |method, actions|
430
- actions.each do |action|
431
- [method].flatten.each do |m|
432
- action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
433
- action_path ||= action
434
-
435
- map_resource_routes(map, resource, action, "#{resource.path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.name_prefix}#{resource.plural}", m)
436
- end
437
- end
438
- end
439
- end
440
-
441
- def map_default_collection_actions(map, resource)
442
- index_route_name = "#{resource.name_prefix}#{resource.plural}"
443
-
444
- if resource.uncountable?
445
- index_route_name << "_index"
446
- end
447
-
448
- map_resource_routes(map, resource, :index, resource.path, index_route_name)
449
- map_resource_routes(map, resource, :create, resource.path, index_route_name)
450
- end
451
-
452
- def map_default_singleton_actions(map, resource)
453
- map_resource_routes(map, resource, :create, resource.path, "#{resource.shallow_name_prefix}#{resource.singular}")
454
- end
455
-
456
- def map_new_actions(map, resource)
457
- resource.new_methods.each do |method, actions|
458
- actions.each do |action|
459
- route_path = resource.new_path
460
- route_name = "new_#{resource.name_prefix}#{resource.singular}"
461
-
462
- unless action == :new
463
- route_path = "#{route_path}#{resource.action_separator}#{action}"
464
- route_name = "#{action}_#{route_name}"
465
- end
466
-
467
- map_resource_routes(map, resource, action, route_path, route_name, method)
468
- end
469
- end
470
- end
471
-
472
- def map_member_actions(map, resource)
473
- resource.member_methods.each do |method, actions|
474
- actions.each do |action|
475
- [method].flatten.each do |m|
476
- action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
477
- action_path ||= @set.resources_path_names[action] || action
478
-
479
- map_resource_routes(map, resource, action, "#{resource.member_path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", m, { :force_id => true })
480
- end
481
- end
482
- end
483
-
484
- route_path = "#{resource.shallow_name_prefix}#{resource.singular}"
485
- map_resource_routes(map, resource, :show, resource.member_path, route_path)
486
- map_resource_routes(map, resource, :update, resource.member_path, route_path)
487
- map_resource_routes(map, resource, :destroy, resource.member_path, route_path)
488
- end
489
-
490
- def map_resource_routes(map, resource, action, route_path, route_name = nil, method = nil, resource_options = {} )
491
- if resource.has_action?(action)
492
- action_options = action_options_for(action, resource, method, resource_options)
493
- formatted_route_path = "#{route_path}.:format"
494
-
495
- if route_name && @set.named_routes[route_name.to_sym].nil?
496
- map.named_route(route_name, formatted_route_path, action_options)
497
- else
498
- map.connect(formatted_route_path, action_options)
499
- end
500
- end
501
- end
502
-
503
- def add_conditions_for(conditions, method)
504
- {:conditions => conditions.dup}.tap do |options|
505
- options[:conditions][:method] = method unless method == :any
506
- end
507
- end
508
-
509
- def action_options_for(action, resource, method = nil, resource_options = {})
510
- default_options = { :action => action.to_s }
511
- require_id = !resource.kind_of?(SingletonResource)
512
- force_id = resource_options[:force_id] && !resource.kind_of?(SingletonResource)
513
-
514
- case default_options[:action]
515
- when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements)
516
- when "create"; default_options.merge(add_conditions_for(resource.conditions, method || :post)).merge(resource.requirements)
517
- when "show", "edit"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements(require_id))
518
- when "update"; default_options.merge(add_conditions_for(resource.conditions, method || :put)).merge(resource.requirements(require_id))
519
- when "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id))
520
- else default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements(force_id))
521
- end
522
- end
523
- end
524
- end
525
- end