actionpack 3.0.0.beta → 3.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. data/CHANGELOG +291 -260
  2. data/lib/abstract_controller.rb +5 -2
  3. data/lib/abstract_controller/assigns.rb +21 -0
  4. data/lib/abstract_controller/base.rb +13 -5
  5. data/lib/abstract_controller/collector.rb +2 -0
  6. data/lib/abstract_controller/helpers.rb +4 -14
  7. data/lib/abstract_controller/layouts.rb +50 -99
  8. data/lib/abstract_controller/logger.rb +2 -2
  9. data/lib/abstract_controller/rendering.rb +105 -173
  10. data/lib/abstract_controller/view_paths.rb +69 -0
  11. data/lib/action_controller.rb +1 -2
  12. data/lib/action_controller/base.rb +10 -32
  13. data/lib/action_controller/caching.rb +19 -18
  14. data/lib/action_controller/caching/actions.rb +17 -11
  15. data/lib/action_controller/caching/fragments.rb +5 -17
  16. data/lib/action_controller/caching/pages.rb +24 -24
  17. data/lib/action_controller/caching/sweeping.rb +1 -3
  18. data/lib/action_controller/deprecated.rb +0 -2
  19. data/lib/action_controller/deprecated/base.rb +143 -0
  20. data/lib/action_controller/metal.rb +29 -26
  21. data/lib/action_controller/metal/compatibility.rb +18 -87
  22. data/lib/action_controller/metal/cookies.rb +0 -1
  23. data/lib/action_controller/metal/head.rb +1 -0
  24. data/lib/action_controller/metal/helpers.rb +2 -2
  25. data/lib/action_controller/metal/hide_actions.rb +4 -6
  26. data/lib/action_controller/metal/http_authentication.rb +18 -33
  27. data/lib/action_controller/metal/implicit_render.rb +21 -0
  28. data/lib/action_controller/metal/instrumentation.rb +1 -1
  29. data/lib/action_controller/metal/mime_responds.rb +2 -1
  30. data/lib/action_controller/metal/rack_delegation.rb +3 -8
  31. data/lib/action_controller/metal/redirecting.rb +2 -1
  32. data/lib/action_controller/metal/renderers.rb +4 -2
  33. data/lib/action_controller/metal/rendering.rb +31 -44
  34. data/lib/action_controller/metal/request_forgery_protection.rb +41 -4
  35. data/lib/action_controller/metal/responder.rb +2 -0
  36. data/lib/action_controller/metal/session_management.rb +0 -36
  37. data/lib/action_controller/metal/streaming.rb +20 -47
  38. data/lib/action_controller/metal/testing.rb +0 -1
  39. data/lib/action_controller/metal/url_for.rb +11 -148
  40. data/lib/action_controller/middleware.rb +2 -1
  41. data/lib/action_controller/polymorphic_routes.rb +1 -2
  42. data/lib/action_controller/railtie.rb +63 -10
  43. data/lib/action_controller/railties/{subscriber.rb → log_subscriber.rb} +5 -12
  44. data/lib/action_controller/railties/url_helpers.rb +14 -0
  45. data/lib/action_controller/record_identifier.rb +20 -1
  46. data/lib/action_controller/test_case.rb +123 -12
  47. data/lib/action_dispatch.rb +1 -0
  48. data/lib/action_dispatch/http/cache.rb +20 -3
  49. data/lib/action_dispatch/http/filter_parameters.rb +40 -25
  50. data/lib/action_dispatch/http/mime_negotiation.rb +6 -17
  51. data/lib/action_dispatch/http/mime_type.rb +2 -7
  52. data/lib/action_dispatch/http/request.rb +12 -33
  53. data/lib/action_dispatch/http/response.rb +35 -15
  54. data/lib/action_dispatch/http/upload.rb +2 -0
  55. data/lib/action_dispatch/http/url.rb +5 -32
  56. data/lib/action_dispatch/middleware/callbacks.rb +1 -1
  57. data/lib/action_dispatch/middleware/cookies.rb +4 -3
  58. data/lib/action_dispatch/middleware/params_parser.rb +4 -3
  59. data/lib/action_dispatch/middleware/remote_ip.rb +51 -0
  60. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -0
  61. data/lib/action_dispatch/middleware/session/cookie_store.rb +6 -8
  62. data/lib/action_dispatch/middleware/show_exceptions.rb +0 -14
  63. data/lib/action_dispatch/middleware/stack.rb +6 -2
  64. data/lib/action_dispatch/railtie.rb +3 -1
  65. data/lib/action_dispatch/routing.rb +2 -0
  66. data/lib/action_dispatch/routing/deprecated_mapper.rb +35 -7
  67. data/lib/action_dispatch/routing/mapper.rb +134 -48
  68. data/lib/action_dispatch/routing/route.rb +2 -2
  69. data/lib/action_dispatch/routing/route_set.rb +217 -158
  70. data/lib/action_dispatch/routing/url_for.rb +139 -0
  71. data/lib/action_dispatch/testing/assertions/response.rb +14 -61
  72. data/lib/action_dispatch/testing/assertions/routing.rb +25 -14
  73. data/lib/action_dispatch/testing/integration.rb +32 -50
  74. data/lib/action_dispatch/testing/performance_test.rb +3 -1
  75. data/lib/action_dispatch/testing/test_process.rb +2 -0
  76. data/lib/action_dispatch/testing/test_request.rb +2 -0
  77. data/lib/action_pack/version.rb +4 -3
  78. data/lib/action_view.rb +11 -6
  79. data/lib/action_view/base.rb +33 -121
  80. data/lib/action_view/context.rb +0 -2
  81. data/lib/action_view/helpers.rb +26 -23
  82. data/lib/action_view/helpers/active_model_helper.rb +28 -18
  83. data/lib/action_view/helpers/asset_tag_helper.rb +109 -54
  84. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  85. data/lib/action_view/helpers/cache_helper.rb +22 -1
  86. data/lib/action_view/helpers/capture_helper.rb +22 -22
  87. data/lib/action_view/helpers/date_helper.rb +6 -5
  88. data/lib/action_view/helpers/form_helper.rb +78 -63
  89. data/lib/action_view/helpers/form_options_helper.rb +6 -4
  90. data/lib/action_view/helpers/form_tag_helper.rb +26 -15
  91. data/lib/action_view/helpers/javascript_helper.rb +90 -10
  92. data/lib/action_view/helpers/number_helper.rb +315 -118
  93. data/lib/action_view/helpers/prototype_helper.rb +19 -46
  94. data/lib/action_view/helpers/record_tag_helper.rb +4 -4
  95. data/lib/action_view/helpers/tag_helper.rb +7 -24
  96. data/lib/action_view/helpers/text_helper.rb +8 -7
  97. data/lib/action_view/helpers/translation_helper.rb +7 -5
  98. data/lib/action_view/helpers/url_helper.rb +19 -16
  99. data/lib/action_view/locale/en.yml +45 -6
  100. data/lib/action_view/lookup_context.rb +190 -0
  101. data/lib/action_view/paths.rb +22 -63
  102. data/lib/action_view/railtie.rb +14 -4
  103. data/lib/action_view/railties/{subscriber.rb → log_subscriber.rb} +1 -1
  104. data/lib/action_view/render/layouts.rb +73 -0
  105. data/lib/action_view/render/partials.rb +15 -41
  106. data/lib/action_view/render/rendering.rb +27 -78
  107. data/lib/action_view/template.rb +20 -24
  108. data/lib/action_view/template/error.rb +22 -2
  109. data/lib/action_view/template/handlers/erb.rb +33 -9
  110. data/lib/action_view/template/handlers/rjs.rb +1 -2
  111. data/lib/action_view/template/resolver.rb +46 -104
  112. data/lib/action_view/template/text.rb +5 -12
  113. data/lib/action_view/test_case.rb +14 -23
  114. metadata +83 -40
  115. data/lib/abstract_controller/compatibility.rb +0 -18
  116. data/lib/abstract_controller/localized_cache.rb +0 -49
  117. data/lib/action_controller/metal/configuration.rb +0 -28
  118. data/lib/action_controller/url_rewriter.rb +0 -76
@@ -3,6 +3,7 @@ require 'cgi'
3
3
  require 'action_view/helpers/url_helper'
4
4
  require 'action_view/helpers/tag_helper'
5
5
  require 'active_support/core_ext/file'
6
+ require 'active_support/core_ext/object/blank'
6
7
 
7
8
  module ActionView
8
9
  module Helpers #:nodoc:
@@ -11,7 +12,7 @@ module ActionView
11
12
  # the assets exist before linking to them:
12
13
  #
13
14
  # image_tag("rails.png")
14
- # # => <img alt="Rails src="/images/rails.png?1230601161" />
15
+ # # => <img alt="Rails" src="/images/rails.png?1230601161" />
15
16
  # stylesheet_link_tag("application")
16
17
  # # => <link href="/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
17
18
  #
@@ -58,7 +59,7 @@ module ActionView
58
59
  # +asset_host+ to a proc like this:
59
60
  #
60
61
  # ActionController::Base.asset_host = Proc.new { |source|
61
- # "http://assets#{rand(2) + 1}.example.com"
62
+ # "http://assets#{source.hash % 2 + 1}.example.com"
62
63
  # }
63
64
  # image_tag("rails.png")
64
65
  # # => <img alt="Rails" src="http://assets0.example.com/images/rails.png?1230601161" />
@@ -66,7 +67,7 @@ module ActionView
66
67
  # # => <link href="http://assets1.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
67
68
  #
68
69
  # The example above generates "http://assets1.example.com" and
69
- # "http://assets2.example.com" randomly. This option is useful for example if
70
+ # "http://assets2.example.com". This option is useful for example if
70
71
  # you need fewer/more than four hosts, custom host names, etc.
71
72
  #
72
73
  # As you see the proc takes a +source+ parameter. That's a string with the
@@ -107,7 +108,7 @@ module ActionView
107
108
  # "http://asset%d.example.com", "https://asset1.example.com"
108
109
  # )
109
110
  #
110
- # === Using asset timestamps
111
+ # === Customizing the asset path
111
112
  #
112
113
  # By default, Rails appends asset's timestamps to all asset paths. This allows
113
114
  # you to set a cache-expiration date for the asset far into the future, but
@@ -132,14 +133,66 @@ module ActionView
132
133
  # will request the same assets over and over again even thought they didn't
133
134
  # change. You can use something like Live HTTP Headers for Firefox to verify
134
135
  # that the cache is indeed working.
136
+ #
137
+ # This strategy works well enough for most server setups and requires the
138
+ # least configuration, but if you deploy several application servers at
139
+ # different times - say to handle a temporary spike in load - then the
140
+ # asset time stamps will be out of sync. In a setup like this you may want
141
+ # to set the way that asset paths are generated yourself.
142
+ #
143
+ # Altering the asset paths that Rails generates can be done in two ways.
144
+ # The easiest is to define the RAILS_ASSET_ID environment variable. The
145
+ # contents of this variable will always be used in preference to
146
+ # calculated timestamps. A more complex but flexible way is to set
147
+ # <tt>ActionController::Base.config.asset_path</tt> to a proc
148
+ # that takes the unmodified asset path and returns the path needed for
149
+ # your asset caching to work. Typically you'd do something like this in
150
+ # <tt>config/environments/production.rb</tt>:
151
+ #
152
+ # # Normally you'd calculate RELEASE_NUMBER at startup.
153
+ # RELEASE_NUMBER = 12345
154
+ # config.action_controller.asset_path_template = proc { |asset_path|
155
+ # "/release-#{RELEASE_NUMBER}#{asset_path}"
156
+ # }
157
+ #
158
+ # This example would cause the following behaviour on all servers no
159
+ # matter when they were deployed:
160
+ #
161
+ # image_tag("rails.png")
162
+ # # => <img alt="Rails" src="/release-12345/images/rails.png" />
163
+ # stylesheet_link_tag("application")
164
+ # # => <link href="/release-12345/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
165
+ #
166
+ # Changing the asset_path does require that your web servers have
167
+ # knowledge of the asset template paths that you rewrite to so it's not
168
+ # suitable for out-of-the-box use. To use the example given above you
169
+ # could use something like this in your Apache VirtualHost configuration:
170
+ #
171
+ # <LocationMatch "^/release-\d+/(images|javascripts|stylesheets)/.*$">
172
+ # # Some browsers still send conditional-GET requests if there's a
173
+ # # Last-Modified header or an ETag header even if they haven't
174
+ # # reached the expiry date sent in the Expires header.
175
+ # Header unset Last-Modified
176
+ # Header unset ETag
177
+ # FileETag None
178
+ #
179
+ # # Assets requested using a cache-busting filename should be served
180
+ # # only once and then cached for a really long time. The HTTP/1.1
181
+ # # spec frowns on hugely-long expiration times though and suggests
182
+ # # that assets which never expire be served with an expiration date
183
+ # # 1 year from access.
184
+ # ExpiresActive On
185
+ # ExpiresDefault "access plus 1 year"
186
+ # </LocationMatch>
187
+ #
188
+ # # We use cached-busting location names with the far-future expires
189
+ # # headers to ensure that if a file does change it can force a new
190
+ # # request. The actual asset filenames are still the same though so we
191
+ # # need to rewrite the location from the cache-busting location to the
192
+ # # real asset location so that we can serve it.
193
+ # RewriteEngine On
194
+ # RewriteRule ^/release-\d+/(images|javascripts|stylesheets)/(.*)$ /$1/$2 [L]
135
195
  module AssetTagHelper
136
- assets_dir = defined?(Rails.public_path) ? Rails.public_path : "public"
137
- ActionView::DEFAULT_CONFIG = {
138
- :assets_dir => assets_dir,
139
- :javascripts_dir => "#{assets_dir}/javascripts",
140
- :stylesheets_dir => "#{assets_dir}/stylesheets",
141
- }
142
-
143
196
  JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
144
197
 
145
198
  # Returns a link tag that browsers and news readers can use to auto-detect
@@ -249,12 +302,12 @@ module ActionView
249
302
  # == Caching multiple javascripts into one
250
303
  #
251
304
  # You can also cache multiple javascripts into one file, which requires less HTTP connections to download and can better be
252
- # compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching
305
+ # compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching
253
306
  # is set to <tt>true</tt> (which is the case by default for the Rails production environment, but not for the development
254
307
  # environment).
255
308
  #
256
309
  # ==== Examples
257
- # javascript_include_tag :all, :cache => true # when ActionController::Base.perform_caching is false =>
310
+ # javascript_include_tag :all, :cache => true # when config.perform_caching is false =>
258
311
  # <script type="text/javascript" src="/javascripts/prototype.js"></script>
259
312
  # <script type="text/javascript" src="/javascripts/effects.js"></script>
260
313
  # ...
@@ -262,15 +315,15 @@ module ActionView
262
315
  # <script type="text/javascript" src="/javascripts/shop.js"></script>
263
316
  # <script type="text/javascript" src="/javascripts/checkout.js"></script>
264
317
  #
265
- # javascript_include_tag :all, :cache => true # when ActionController::Base.perform_caching is true =>
318
+ # javascript_include_tag :all, :cache => true # when config.perform_caching is true =>
266
319
  # <script type="text/javascript" src="/javascripts/all.js"></script>
267
320
  #
268
- # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is false =>
321
+ # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when config.perform_caching is false =>
269
322
  # <script type="text/javascript" src="/javascripts/prototype.js"></script>
270
323
  # <script type="text/javascript" src="/javascripts/cart.js"></script>
271
324
  # <script type="text/javascript" src="/javascripts/checkout.js"></script>
272
325
  #
273
- # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is true =>
326
+ # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when config.perform_caching is true =>
274
327
  # <script type="text/javascript" src="/javascripts/shop.js"></script>
275
328
  #
276
329
  # The <tt>:recursive</tt> option is also available for caching:
@@ -282,11 +335,11 @@ module ActionView
282
335
  cache = concat || options.delete("cache")
283
336
  recursive = options.delete("recursive")
284
337
 
285
- if concat || (ActionController::Base.perform_caching && cache)
338
+ if concat || (config.perform_caching && cache)
286
339
  joined_javascript_name = (cache == true ? "all" : cache) + ".js"
287
340
  joined_javascript_path = File.join(joined_javascript_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.javascripts_dir, joined_javascript_name)
288
341
 
289
- unless ActionController::Base.perform_caching && File.exists?(joined_javascript_path)
342
+ unless config.perform_caching && File.exists?(joined_javascript_path)
290
343
  write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive))
291
344
  end
292
345
  javascript_src_tag(joined_javascript_name, options)
@@ -397,25 +450,25 @@ module ActionView
397
450
  # == Caching multiple stylesheets into one
398
451
  #
399
452
  # You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be
400
- # compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching
453
+ # compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching
401
454
  # is set to true (which is the case by default for the Rails production environment, but not for the development
402
455
  # environment). Examples:
403
456
  #
404
457
  # ==== Examples
405
- # stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is false =>
458
+ # stylesheet_link_tag :all, :cache => true # when config.perform_caching is false =>
406
459
  # <link href="/stylesheets/style1.css" media="screen" rel="stylesheet" type="text/css" />
407
460
  # <link href="/stylesheets/styleB.css" media="screen" rel="stylesheet" type="text/css" />
408
461
  # <link href="/stylesheets/styleX2.css" media="screen" rel="stylesheet" type="text/css" />
409
462
  #
410
- # stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is true =>
463
+ # stylesheet_link_tag :all, :cache => true # when config.perform_caching is true =>
411
464
  # <link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />
412
465
  #
413
- # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when ActionController::Base.perform_caching is false =>
466
+ # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when config.perform_caching is false =>
414
467
  # <link href="/stylesheets/shop.css" media="screen" rel="stylesheet" type="text/css" />
415
468
  # <link href="/stylesheets/cart.css" media="screen" rel="stylesheet" type="text/css" />
416
469
  # <link href="/stylesheets/checkout.css" media="screen" rel="stylesheet" type="text/css" />
417
470
  #
418
- # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when ActionController::Base.perform_caching is true =>
471
+ # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when config.perform_caching is true =>
419
472
  # <link href="/stylesheets/payment.css" media="screen" rel="stylesheet" type="text/css" />
420
473
  #
421
474
  # The <tt>:recursive</tt> option is also available for caching:
@@ -433,11 +486,11 @@ module ActionView
433
486
  cache = concat || options.delete("cache")
434
487
  recursive = options.delete("recursive")
435
488
 
436
- if concat || (ActionController::Base.perform_caching && cache)
489
+ if concat || (config.perform_caching && cache)
437
490
  joined_stylesheet_name = (cache == true ? "all" : cache) + ".css"
438
491
  joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.stylesheets_dir, joined_stylesheet_name)
439
492
 
440
- unless ActionController::Base.perform_caching && File.exists?(joined_stylesheet_path)
493
+ unless config.perform_caching && File.exists?(joined_stylesheet_path)
441
494
  write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive))
442
495
  end
443
496
  stylesheet_tag(joined_stylesheet_name, options)
@@ -530,7 +583,7 @@ module ActionView
530
583
  options.symbolize_keys!
531
584
 
532
585
  src = options[:src] = path_to_image(source)
533
- options[:alt] ||= File.basename(src, '.*').split('.').first.to_s.capitalize
586
+ options[:alt] ||= File.basename(src, '.*').capitalize
534
587
 
535
588
  if size = options.delete(:size)
536
589
  options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$}
@@ -630,41 +683,37 @@ module ActionView
630
683
  @@cache_asset_timestamps = true
631
684
 
632
685
  private
686
+ def rewrite_extension?(source, dir, ext)
687
+ source_ext = File.extname(source)[1..-1]
688
+ ext && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(config.assets_dir, dir, "#{source}.#{ext}"))))
689
+ end
690
+
691
+ def rewrite_host_and_protocol(source, has_request)
692
+ host = compute_asset_host(source)
693
+ if has_request && host.present? && !is_uri?(host)
694
+ host = "#{controller.request.protocol}#{host}"
695
+ end
696
+ "#{host}#{source}"
697
+ end
698
+
633
699
  # Add the the extension +ext+ if not present. Return full URLs otherwise untouched.
634
700
  # Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
635
701
  # roots. Rewrite the asset path for cache-busting asset ids. Include
636
702
  # asset host, if configured, with the correct request protocol.
637
703
  def compute_public_path(source, dir, ext = nil, include_host = true)
638
- has_request = controller.respond_to?(:request)
704
+ return source if is_uri?(source)
639
705
 
640
- source_ext = File.extname(source)[1..-1]
641
- if ext && !is_uri?(source) && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(config.assets_dir, dir, "#{source}.#{ext}"))))
642
- source += ".#{ext}"
643
- end
706
+ source += ".#{ext}" if rewrite_extension?(source, dir, ext)
707
+ source = "/#{dir}/#{source}" unless source[0] == ?/
708
+ source = rewrite_asset_path(source, config.asset_path)
644
709
 
645
- unless is_uri?(source)
646
- source = "/#{dir}/#{source}" unless source[0] == ?/
647
-
648
- source = rewrite_asset_path(source)
649
-
650
- if has_request && include_host
651
- unless source =~ %r{^#{ActionController::Base.relative_url_root}/}
652
- source = "#{ActionController::Base.relative_url_root}#{source}"
653
- end
654
- end
710
+ has_request = controller.respond_to?(:request)
711
+ if has_request && include_host && source !~ %r{^#{controller.config.relative_url_root}/}
712
+ source = "#{controller.config.relative_url_root}#{source}"
655
713
  end
714
+ source = rewrite_host_and_protocol(source, has_request) if include_host
656
715
 
657
- if include_host && !is_uri?(source)
658
- host = compute_asset_host(source)
659
-
660
- if has_request && !host.blank? && !is_uri?(host)
661
- host = "#{controller.request.protocol}#{host}"
662
- end
663
-
664
- "#{host}#{source}"
665
- else
666
- source
667
- end
716
+ source
668
717
  end
669
718
 
670
719
  def is_uri?(path)
@@ -677,7 +726,7 @@ module ActionView
677
726
  # or the value returned from invoking the proc if it's a proc or the value from
678
727
  # invoking call if it's an object responding to call.
679
728
  def compute_asset_host(source)
680
- if host = ActionController::Base.asset_host
729
+ if host = config.asset_host
681
730
  if host.is_a?(Proc) || host.respond_to?(:call)
682
731
  case host.is_a?(Proc) ? host.arity : host.method(:call).arity
683
732
  when 2
@@ -720,7 +769,13 @@ module ActionView
720
769
 
721
770
  # Break out the asset path rewrite in case plugins wish to put the asset id
722
771
  # someplace other than the query string.
723
- def rewrite_asset_path(source)
772
+ def rewrite_asset_path(source, path = nil)
773
+ if path && path.respond_to?(:call)
774
+ return path.call(source)
775
+ elsif path && path.is_a?(String)
776
+ return path % [source]
777
+ end
778
+
724
779
  asset_id = rails_asset_id(source)
725
780
  if asset_id.blank?
726
781
  source
@@ -8,7 +8,7 @@ module ActionView
8
8
  # Full usage example:
9
9
  #
10
10
  # config/routes.rb:
11
- # ActionController::Routing::Routes.draw do |map|
11
+ # Basecamp::Application.routes.draw do |map|
12
12
  # map.resources :posts
13
13
  # map.root :controller => "posts"
14
14
  # end
@@ -114,7 +114,7 @@ module ActionView
114
114
  feed_opts.merge!(options).reject!{|k,v| !k.to_s.match(/^xml/)}
115
115
 
116
116
  xml.feed(feed_opts) do
117
- xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.request_uri.split(".")[0]}")
117
+ xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}")
118
118
  xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:root_url] || (request.protocol + request.host_with_port))
119
119
  xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:url] || request.url)
120
120
 
@@ -32,7 +32,28 @@ module ActionView
32
32
  # <i>Topics listed alphabetically</i>
33
33
  # <% end %>
34
34
  def cache(name = {}, options = nil, &block)
35
- controller.fragment_for(output_buffer, name, options, &block)
35
+ safe_concat fragment_for(name, options, &block)
36
+ nil
37
+ end
38
+
39
+ private
40
+ # TODO: Create an object that has caching read/write on it
41
+ def fragment_for(name = {}, options = nil, &block) #:nodoc:
42
+ if controller.perform_caching
43
+ if controller.fragment_exist?(name, options)
44
+ controller.read_fragment(name, options)
45
+ else
46
+ # VIEW TODO: Make #capture usable outside of ERB
47
+ # This dance is needed because Builder can't use capture
48
+ pos = output_buffer.length
49
+ yield
50
+ fragment = output_buffer.slice!(pos..-1)
51
+ controller.write_fragment(name, fragment, options)
52
+ end
53
+ else
54
+ ret = yield
55
+ ActiveSupport::SafeBuffer.new(ret) if ret.is_a?(String)
56
+ end
36
57
  end
37
58
  end
38
59
  end
@@ -1,23 +1,25 @@
1
+ require 'active_support/core_ext/object/blank'
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  # CaptureHelper exposes methods to let you extract generated markup which
4
6
  # can be used in other parts of a template or layout file.
5
- # It provides a method to capture blocks into variables through capture and
7
+ # It provides a method to capture blocks into variables through capture and
6
8
  # a way to capture a block of markup for use in a layout through content_for.
7
9
  module CaptureHelper
8
- # The capture method allows you to extract part of a template into a
9
- # variable. You can then use this variable anywhere in your templates or layout.
10
- #
10
+ # The capture method allows you to extract part of a template into a
11
+ # variable. You can then use this variable anywhere in your templates or layout.
12
+ #
11
13
  # ==== Examples
12
14
  # The capture method can be used in ERb templates...
13
- #
15
+ #
14
16
  # <% @greeting = capture do %>
15
17
  # Welcome to my shiny new web page! The date and time is
16
18
  # <%= Time.now %>
17
19
  # <% end %>
18
20
  #
19
21
  # ...and Builder (RXML) templates.
20
- #
22
+ #
21
23
  # @timestamp = capture do
22
24
  # "The current timestamp is #{Time.now}."
23
25
  # end
@@ -30,22 +32,20 @@ module ActionView
30
32
  # <b><%= @greeting %></b>
31
33
  # </body></html>
32
34
  #
33
- def capture(*args, &block)
34
- # Return captured buffer in erb.
35
- if block_called_from_erb?(block)
36
- with_output_buffer { block.call(*args) }
37
- else
38
- # Return block result otherwise, but protect buffer also.
39
- with_output_buffer { return block.call(*args) }
35
+ def capture(*args)
36
+ value = nil
37
+ buffer = with_output_buffer { value = yield(*args) }
38
+ if string = buffer.presence || value and string.is_a?(String)
39
+ NonConcattingString.new(string)
40
40
  end
41
41
  end
42
42
 
43
43
  # Calling content_for stores a block of markup in an identifier for later use.
44
44
  # You can make subsequent calls to the stored content in other templates or the layout
45
45
  # by passing the identifier as an argument to <tt>yield</tt>.
46
- #
46
+ #
47
47
  # ==== Examples
48
- #
48
+ #
49
49
  # <% content_for :not_authorized do %>
50
50
  # alert('You are not authorized to do that!')
51
51
  # <% end %>
@@ -79,7 +79,7 @@ module ActionView
79
79
  #
80
80
  # Then, in another view, you could to do something like this:
81
81
  #
82
- # <%= link_to_remote 'Logout', :action => 'logout' %>
82
+ # <%= link_to 'Logout', :action => 'logout', :remote => true %>
83
83
  #
84
84
  # <% content_for :script do %>
85
85
  # <%= javascript_include_tag :defaults %>
@@ -96,7 +96,7 @@ module ActionView
96
96
  # <% end %>
97
97
  #
98
98
  # <%# Add some other content, or use a different template: %>
99
- #
99
+ #
100
100
  # <% content_for :navigation do %>
101
101
  # <li><%= link_to 'Login', :action => 'login' %></li>
102
102
  # <% end %>
@@ -113,13 +113,13 @@ module ActionView
113
113
  # for elements that will be fragment cached.
114
114
  def content_for(name, content = nil, &block)
115
115
  content = capture(&block) if block_given?
116
- return @_content_for[name] << content if content
117
- @_content_for[name]
116
+ @_content_for[name] << content if content
117
+ @_content_for[name] unless content
118
118
  end
119
119
 
120
120
  # content_for? simply checks whether any content has been captured yet using content_for
121
121
  # Useful to render parts of your layout differently based on what is in your views.
122
- #
122
+ #
123
123
  # ==== Examples
124
124
  #
125
125
  # Perhaps you will use different css in you layout if no content_for :right_column
@@ -143,8 +143,8 @@ module ActionView
143
143
  # Defaults to a new empty string.
144
144
  def with_output_buffer(buf = nil) #:nodoc:
145
145
  unless buf
146
- buf = ActiveSupport::SafeBuffer.new
147
- buf.force_encoding(output_buffer.encoding) if buf.respond_to?(:force_encoding)
146
+ buf = ActionView::OutputBuffer.new
147
+ buf.force_encoding(output_buffer.encoding) if output_buffer && buf.respond_to?(:force_encoding)
148
148
  end
149
149
  self.output_buffer, old_buffer = buf, output_buffer
150
150
  yield