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
@@ -0,0 +1,147 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'active_support/core_ext/string/inflections'
3
+ require 'active_support/core_ext/file'
4
+ require 'action_view/helpers/tag_helper'
5
+
6
+ module ActionView
7
+ module Helpers
8
+ module AssetTagHelper
9
+
10
+ class AssetIncludeTag
11
+ include TagHelper
12
+
13
+ attr_reader :config, :asset_paths
14
+ class_attribute :expansions
15
+
16
+ def self.inherited(base)
17
+ base.expansions = { }
18
+ end
19
+
20
+ def initialize(config, asset_paths)
21
+ @config = config
22
+ @asset_paths = asset_paths
23
+ end
24
+
25
+ def asset_name
26
+ raise NotImplementedError
27
+ end
28
+
29
+ def extension
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def custom_dir
34
+ raise NotImplementedError
35
+ end
36
+
37
+ def asset_tag(source, options)
38
+ raise NotImplementedError
39
+ end
40
+
41
+ def include_tag(*sources)
42
+ options = sources.extract_options!.stringify_keys
43
+ concat = options.delete("concat")
44
+ cache = concat || options.delete("cache")
45
+ recursive = options.delete("recursive")
46
+
47
+ if concat || (config.perform_caching && cache)
48
+ joined_name = (cache == true ? "all" : cache) + ".#{extension}"
49
+ joined_path = File.join((joined_name[/^#{File::SEPARATOR}/] ? config.assets_dir : custom_dir), joined_name)
50
+ unless config.perform_caching && File.exists?(joined_path)
51
+ write_asset_file_contents(joined_path, compute_paths(sources, recursive))
52
+ end
53
+ asset_tag(joined_name, options)
54
+ else
55
+ sources = expand_sources(sources, recursive)
56
+ ensure_sources!(sources) if cache
57
+ sources.collect { |source| asset_tag(source, options) }.join("\n").html_safe
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def path_to_asset(source, include_host = true)
64
+ asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host)
65
+ end
66
+
67
+ def compute_paths(*args)
68
+ expand_sources(*args).collect { |source| asset_paths.compute_public_path(source, asset_name.pluralize, extension, false) }
69
+ end
70
+
71
+ def expand_sources(sources, recursive)
72
+ if sources.first == :all
73
+ collect_asset_files(custom_dir, ('**' if recursive), "*.#{extension}")
74
+ else
75
+ sources.inject([]) do |list, source|
76
+ determined_source = determine_source(source, expansions)
77
+ update_source_list(list, determined_source)
78
+ end
79
+ end
80
+ end
81
+
82
+ def update_source_list(list, source)
83
+ case source
84
+ when String
85
+ list.delete(source)
86
+ list << source
87
+ when Array
88
+ updated_sources = source - list
89
+ list.concat(updated_sources)
90
+ end
91
+ end
92
+
93
+ def ensure_sources!(sources)
94
+ sources.each do |source|
95
+ asset_file_path!(path_to_asset(source, false))
96
+ end
97
+ end
98
+
99
+ def collect_asset_files(*path)
100
+ dir = path.first
101
+
102
+ Dir[File.join(*path.compact)].collect do |file|
103
+ file[-(file.size - dir.size - 1)..-1].sub(/\.\w+$/, '')
104
+ end.sort
105
+ end
106
+
107
+ def determine_source(source, collection)
108
+ case source
109
+ when Symbol
110
+ collection[source] || raise(ArgumentError, "No expansion found for #{source.inspect}")
111
+ else
112
+ source
113
+ end
114
+ end
115
+
116
+ def join_asset_file_contents(paths)
117
+ paths.collect { |path| File.read(asset_file_path!(path, true)) }.join("\n\n")
118
+ end
119
+
120
+ def write_asset_file_contents(joined_asset_path, asset_paths)
121
+ FileUtils.mkdir_p(File.dirname(joined_asset_path))
122
+ File.atomic_write(joined_asset_path) { |cache| cache.write(join_asset_file_contents(asset_paths)) }
123
+
124
+ # Set mtime to the latest of the combined files to allow for
125
+ # consistent ETag without a shared filesystem.
126
+ mt = asset_paths.map { |p| File.mtime(asset_file_path(p)) }.max
127
+ File.utime(mt, mt, joined_asset_path)
128
+ end
129
+
130
+ def asset_file_path(path)
131
+ File.join(config.assets_dir, path.split('?').first)
132
+ end
133
+
134
+ def asset_file_path!(path, error_if_file_is_uri = false)
135
+ if asset_paths.is_uri?(path)
136
+ raise(Errno::ENOENT, "Asset file #{path} is uri and cannot be merged into single file") if error_if_file_is_uri
137
+ else
138
+ absolute_path = asset_file_path(path)
139
+ raise(Errno::ENOENT, "Asset file not found at '#{absolute_path}'" ) unless File.exist?(absolute_path)
140
+ return absolute_path
141
+ end
142
+ end
143
+ end
144
+
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,101 @@
1
+ require 'active_support/core_ext/file'
2
+ require 'action_view/helpers/asset_paths'
3
+
4
+ module ActionView
5
+ module Helpers
6
+ module AssetTagHelper
7
+
8
+ class AssetPaths < ActionView::Helpers::AssetPaths #:nodoc:
9
+ # You can enable or disable the asset tag ids cache.
10
+ # With the cache enabled, the asset tag helper methods will make fewer
11
+ # expensive file system calls (the default implementation checks the file
12
+ # system timestamp). However this prevents you from modifying any asset
13
+ # files while the server is running.
14
+ #
15
+ # ActionView::Helpers::AssetTagHelper::AssetPaths.cache_asset_ids = false
16
+ mattr_accessor :cache_asset_ids
17
+
18
+ # Add or change an asset id in the asset id cache. This can be used
19
+ # for SASS on Heroku.
20
+ # :api: public
21
+ def add_to_asset_ids_cache(source, asset_id)
22
+ self.asset_ids_cache_guard.synchronize do
23
+ self.asset_ids_cache[source] = asset_id
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def rewrite_extension(source, dir, ext)
30
+ source_ext = File.extname(source)
31
+
32
+ source_with_ext = if source_ext.empty?
33
+ "#{source}.#{ext}"
34
+ elsif ext != source_ext[1..-1]
35
+ with_ext = "#{source}.#{ext}"
36
+ with_ext if File.exist?(File.join(config.assets_dir, dir, with_ext))
37
+ end
38
+
39
+ source_with_ext || source
40
+ end
41
+
42
+ # Break out the asset path rewrite in case plugins wish to put the asset id
43
+ # someplace other than the query string.
44
+ def rewrite_asset_path(source, dir)
45
+ source = "/#{dir}/#{source}" unless source[0] == ?/
46
+ path = config.asset_path
47
+
48
+ if path && path.respond_to?(:call)
49
+ return path.call(source)
50
+ elsif path && path.is_a?(String)
51
+ return path % [source]
52
+ end
53
+
54
+ asset_id = rails_asset_id(source)
55
+ if asset_id.empty?
56
+ source
57
+ else
58
+ "#{source}?#{asset_id}"
59
+ end
60
+ end
61
+
62
+ mattr_accessor :asset_ids_cache
63
+ self.asset_ids_cache = {}
64
+
65
+ mattr_accessor :asset_ids_cache_guard
66
+ self.asset_ids_cache_guard = Mutex.new
67
+
68
+ # Use the RAILS_ASSET_ID environment variable or the source's
69
+ # modification time as its cache-busting asset id.
70
+ def rails_asset_id(source)
71
+ if asset_id = ENV["RAILS_ASSET_ID"]
72
+ asset_id
73
+ else
74
+ if self.cache_asset_ids && (asset_id = self.asset_ids_cache[source])
75
+ asset_id
76
+ else
77
+ path = File.join(config.assets_dir, source)
78
+ asset_id = File.exist?(path) ? File.mtime(path).to_i.to_s : ''
79
+
80
+ if self.cache_asset_ids
81
+ add_to_asset_ids_cache(source, asset_id)
82
+ end
83
+
84
+ asset_id
85
+ end
86
+ end
87
+ end
88
+
89
+ def rewrite_relative_url_root(source, relative_url_root)
90
+ relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
91
+ end
92
+
93
+ def rewrite_host_and_protocol(source, has_request)
94
+ source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request
95
+ super(source, has_request)
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,200 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/file'
3
+ require 'action_view/helpers/asset_tag_helpers/asset_include_tag'
4
+
5
+ module ActionView
6
+ module Helpers
7
+ module AssetTagHelper
8
+
9
+ class JavascriptIncludeTag < AssetIncludeTag
10
+ def asset_name
11
+ 'javascript'
12
+ end
13
+
14
+ def extension
15
+ 'js'
16
+ end
17
+
18
+ def asset_tag(source, options)
19
+ content_tag("script", "", { "type" => Mime::JS, "src" => path_to_asset(source) }.merge(options))
20
+ end
21
+
22
+ def custom_dir
23
+ config.javascripts_dir
24
+ end
25
+
26
+ private
27
+
28
+ def expand_sources(sources, recursive = false)
29
+ if sources.include?(:all)
30
+ all_asset_files = (collect_asset_files(custom_dir, ('**' if recursive), "*.#{extension}") - ['application']) << 'application'
31
+ ((determine_source(:defaults, expansions).dup & all_asset_files) + all_asset_files).uniq
32
+ else
33
+ expanded_sources = sources.inject([]) do |list, source|
34
+ determined_source = determine_source(source, expansions)
35
+ update_source_list(list, determined_source)
36
+ end
37
+ add_application_js(expanded_sources, sources)
38
+ expanded_sources
39
+ end
40
+ end
41
+
42
+ def add_application_js(expanded_sources, sources)
43
+ if sources.include?(:defaults) && File.exist?(File.join(custom_dir, "application.#{extension}"))
44
+ expanded_sources.delete('application')
45
+ expanded_sources << "application"
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ module JavascriptTagHelpers
52
+ extend ActiveSupport::Concern
53
+
54
+ module ClassMethods
55
+ # Register one or more javascript files to be included when <tt>symbol</tt>
56
+ # is passed to <tt>javascript_include_tag</tt>. This method is typically intended
57
+ # to be called from plugin initialization to register javascript files
58
+ # that the plugin installed in <tt>public/javascripts</tt>.
59
+ #
60
+ # ActionView::Helpers::AssetTagHelper.register_javascript_expansion :monkey => ["head", "body", "tail"]
61
+ #
62
+ # javascript_include_tag :monkey # =>
63
+ # <script type="text/javascript" src="/javascripts/head.js"></script>
64
+ # <script type="text/javascript" src="/javascripts/body.js"></script>
65
+ # <script type="text/javascript" src="/javascripts/tail.js"></script>
66
+ def register_javascript_expansion(expansions)
67
+ js_expansions = JavascriptIncludeTag.expansions
68
+ expansions.each do |key, values|
69
+ js_expansions[key] = (js_expansions[key] || []) | Array(values)
70
+ end
71
+ end
72
+ end
73
+
74
+ # Computes the path to a javascript asset in the public javascripts directory.
75
+ # If the +source+ filename has no extension, .js will be appended (except for explicit URIs)
76
+ # Full paths from the document root will be passed through.
77
+ # Used internally by javascript_include_tag to build the script path.
78
+ #
79
+ # ==== Examples
80
+ # javascript_path "xmlhr" # => /javascripts/xmlhr.js
81
+ # javascript_path "dir/xmlhr.js" # => /javascripts/dir/xmlhr.js
82
+ # javascript_path "/dir/xmlhr" # => /dir/xmlhr.js
83
+ # javascript_path "http://www.example.com/js/xmlhr" # => http://www.example.com/js/xmlhr
84
+ # javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js
85
+ def javascript_path(source)
86
+ if config.use_sprockets
87
+ asset_path(source, 'js')
88
+ else
89
+ asset_paths.compute_public_path(source, 'javascripts', 'js')
90
+ end
91
+ end
92
+ alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route
93
+
94
+ # Returns an HTML script tag for each of the +sources+ provided.
95
+ #
96
+ # Sources may be paths to JavaScript files. Relative paths are assumed to be relative
97
+ # to <tt>public/javascripts</tt>, full paths are assumed to be relative to the document
98
+ # root. Relative paths are idiomatic, use absolute paths only when needed.
99
+ #
100
+ # When passing paths, the ".js" extension is optional.
101
+ #
102
+ # If the application is not using the asset pipeline, to include the default JavaScript
103
+ # expansion pass <tt>:defaults</tt> as source. By default, <tt>:defaults</tt> loads jQuery,
104
+ # and that can be overridden in <tt>config/application.rb</tt>:
105
+ #
106
+ # config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js)
107
+ #
108
+ # When using <tt>:defaults</tt>, if an <tt>application.js</tt> file exists in
109
+ # <tt>public/javascripts</tt> it will be included as well at the end.
110
+ #
111
+ # You can modify the HTML attributes of the script tag by passing a hash as the
112
+ # last argument.
113
+ #
114
+ # ==== Examples
115
+ # javascript_include_tag "xmlhr"
116
+ # # => <script type="text/javascript" src="/javascripts/xmlhr.js?1284139606"></script>
117
+ #
118
+ # javascript_include_tag "xmlhr.js"
119
+ # # => <script type="text/javascript" src="/javascripts/xmlhr.js?1284139606"></script>
120
+ #
121
+ # javascript_include_tag "common.javascript", "/elsewhere/cools"
122
+ # # => <script type="text/javascript" src="/javascripts/common.javascript?1284139606"></script>
123
+ # # <script type="text/javascript" src="/elsewhere/cools.js?1423139606"></script>
124
+ #
125
+ # javascript_include_tag "http://www.example.com/xmlhr"
126
+ # # => <script type="text/javascript" src="http://www.example.com/xmlhr.js?1284139606"></script>
127
+ #
128
+ # javascript_include_tag "http://www.example.com/xmlhr.js"
129
+ # # => <script type="text/javascript" src="http://www.example.com/xmlhr.js?1284139606"></script>
130
+ #
131
+ # javascript_include_tag :defaults
132
+ # # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
133
+ # # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
134
+ # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
135
+ #
136
+ # * = The application.js file is only referenced if it exists
137
+ #
138
+ # You can also include all JavaScripts in the +javascripts+ directory using <tt>:all</tt> as the source:
139
+ #
140
+ # javascript_include_tag :all
141
+ # # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
142
+ # # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
143
+ # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
144
+ # # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
145
+ # # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
146
+ #
147
+ # Note that your defaults of choice will be included first, so they will be available to all subsequently
148
+ # included files.
149
+ #
150
+ # If you want Rails to search in all the subdirectories under <tt>public/javascripts</tt>, you should
151
+ # explicitly set <tt>:recursive</tt>:
152
+ #
153
+ # javascript_include_tag :all, :recursive => true
154
+ #
155
+ # == Caching multiple JavaScripts into one
156
+ #
157
+ # You can also cache multiple JavaScripts into one file, which requires less HTTP connections to download
158
+ # and can better be compressed by gzip (leading to faster transfers). Caching will only happen if
159
+ # <tt>config.perform_caching</tt> is set to true (which is the case by default for the Rails
160
+ # production environment, but not for the development environment).
161
+ #
162
+ # ==== Examples
163
+ #
164
+ # # assuming config.perform_caching is false
165
+ # javascript_include_tag :all, :cache => true
166
+ # # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
167
+ # # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
168
+ # # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
169
+ # # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
170
+ # # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
171
+ #
172
+ # # assuming config.perform_caching is true
173
+ # javascript_include_tag :all, :cache => true
174
+ # # => <script type="text/javascript" src="/javascripts/all.js?1344139789"></script>
175
+ #
176
+ # # assuming config.perform_caching is false
177
+ # javascript_include_tag "jquery", "cart", "checkout", :cache => "shop"
178
+ # # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
179
+ # # <script type="text/javascript" src="/javascripts/cart.js?1289139157"></script>
180
+ # # <script type="text/javascript" src="/javascripts/checkout.js?1299139816"></script>
181
+ #
182
+ # # assuming config.perform_caching is true
183
+ # javascript_include_tag "jquery", "cart", "checkout", :cache => "shop"
184
+ # # => <script type="text/javascript" src="/javascripts/shop.js?1299139816"></script>
185
+ #
186
+ # The <tt>:recursive</tt> option is also available for caching:
187
+ #
188
+ # javascript_include_tag :all, :cache => true, :recursive => true
189
+ def javascript_include_tag(*sources)
190
+ if config.use_sprockets
191
+ sprockets_javascript_include_tag(*sources)
192
+ else
193
+ @javascript_include ||= JavascriptIncludeTag.new(config, asset_paths)
194
+ @javascript_include.include_tag(*sources)
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,152 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/file'
3
+ require 'action_view/helpers/asset_tag_helpers/asset_include_tag'
4
+
5
+ module ActionView
6
+ module Helpers
7
+ module AssetTagHelper
8
+
9
+ class StylesheetIncludeTag < AssetIncludeTag
10
+ def asset_name
11
+ 'stylesheet'
12
+ end
13
+
14
+ def extension
15
+ 'css'
16
+ end
17
+
18
+ def asset_tag(source, options)
19
+ tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source)) }.merge(options), false, false)
20
+ end
21
+
22
+ def custom_dir
23
+ config.stylesheets_dir
24
+ end
25
+ end
26
+
27
+
28
+ module StylesheetTagHelpers
29
+ extend ActiveSupport::Concern
30
+
31
+ module ClassMethods
32
+ # Register one or more stylesheet files to be included when <tt>symbol</tt>
33
+ # is passed to <tt>stylesheet_link_tag</tt>. This method is typically intended
34
+ # to be called from plugin initialization to register stylesheet files
35
+ # that the plugin installed in <tt>public/stylesheets</tt>.
36
+ #
37
+ # ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :monkey => ["head", "body", "tail"]
38
+ #
39
+ # stylesheet_link_tag :monkey # =>
40
+ # <link href="/stylesheets/head.css" media="screen" rel="stylesheet" type="text/css" />
41
+ # <link href="/stylesheets/body.css" media="screen" rel="stylesheet" type="text/css" />
42
+ # <link href="/stylesheets/tail.css" media="screen" rel="stylesheet" type="text/css" />
43
+ def register_stylesheet_expansion(expansions)
44
+ style_expansions = StylesheetIncludeTag.expansions
45
+ expansions.each do |key, values|
46
+ style_expansions[key] = (style_expansions[key] || []) | Array(values)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Computes the path to a stylesheet asset in the public stylesheets directory.
52
+ # If the +source+ filename has no extension, <tt>.css</tt> will be appended (except for explicit URIs).
53
+ # Full paths from the document root will be passed through.
54
+ # Used internally by +stylesheet_link_tag+ to build the stylesheet path.
55
+ #
56
+ # ==== Examples
57
+ # stylesheet_path "style" # => /stylesheets/style.css
58
+ # stylesheet_path "dir/style.css" # => /stylesheets/dir/style.css
59
+ # stylesheet_path "/dir/style.css" # => /dir/style.css
60
+ # stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style
61
+ # stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css
62
+ def stylesheet_path(source)
63
+ if config.use_sprockets
64
+ asset_path(source, 'css')
65
+ else
66
+ asset_paths.compute_public_path(source, 'stylesheets', 'css')
67
+ end
68
+ end
69
+ alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
70
+
71
+ # Returns a stylesheet link tag for the sources specified as arguments. If
72
+ # you don't specify an extension, <tt>.css</tt> will be appended automatically.
73
+ # You can modify the link attributes by passing a hash as the last argument.
74
+ #
75
+ # ==== Examples
76
+ # stylesheet_link_tag "style" # =>
77
+ # <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
78
+ #
79
+ # stylesheet_link_tag "style.css" # =>
80
+ # <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
81
+ #
82
+ # stylesheet_link_tag "http://www.example.com/style.css" # =>
83
+ # <link href="http://www.example.com/style.css" media="screen" rel="stylesheet" type="text/css" />
84
+ #
85
+ # stylesheet_link_tag "style", :media => "all" # =>
86
+ # <link href="/stylesheets/style.css" media="all" rel="stylesheet" type="text/css" />
87
+ #
88
+ # stylesheet_link_tag "style", :media => "print" # =>
89
+ # <link href="/stylesheets/style.css" media="print" rel="stylesheet" type="text/css" />
90
+ #
91
+ # stylesheet_link_tag "random.styles", "/css/stylish" # =>
92
+ # <link href="/stylesheets/random.styles" media="screen" rel="stylesheet" type="text/css" />
93
+ # <link href="/css/stylish.css" media="screen" rel="stylesheet" type="text/css" />
94
+ #
95
+ # You can also include all styles in the stylesheets directory using <tt>:all</tt> as the source:
96
+ #
97
+ # stylesheet_link_tag :all # =>
98
+ # <link href="/stylesheets/style1.css" media="screen" rel="stylesheet" type="text/css" />
99
+ # <link href="/stylesheets/styleB.css" media="screen" rel="stylesheet" type="text/css" />
100
+ # <link href="/stylesheets/styleX2.css" media="screen" rel="stylesheet" type="text/css" />
101
+ #
102
+ # If you want Rails to search in all the subdirectories under stylesheets, you should explicitly set <tt>:recursive</tt>:
103
+ #
104
+ # stylesheet_link_tag :all, :recursive => true
105
+ #
106
+ # == Caching multiple stylesheets into one
107
+ #
108
+ # You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be
109
+ # compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching
110
+ # is set to true (which is the case by default for the Rails production environment, but not for the development
111
+ # environment). Examples:
112
+ #
113
+ # ==== Examples
114
+ # stylesheet_link_tag :all, :cache => true # when config.perform_caching is false =>
115
+ # <link href="/stylesheets/style1.css" media="screen" rel="stylesheet" type="text/css" />
116
+ # <link href="/stylesheets/styleB.css" media="screen" rel="stylesheet" type="text/css" />
117
+ # <link href="/stylesheets/styleX2.css" media="screen" rel="stylesheet" type="text/css" />
118
+ #
119
+ # stylesheet_link_tag :all, :cache => true # when config.perform_caching is true =>
120
+ # <link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />
121
+ #
122
+ # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when config.perform_caching is false =>
123
+ # <link href="/stylesheets/shop.css" media="screen" rel="stylesheet" type="text/css" />
124
+ # <link href="/stylesheets/cart.css" media="screen" rel="stylesheet" type="text/css" />
125
+ # <link href="/stylesheets/checkout.css" media="screen" rel="stylesheet" type="text/css" />
126
+ #
127
+ # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when config.perform_caching is true =>
128
+ # <link href="/stylesheets/payment.css" media="screen" rel="stylesheet" type="text/css" />
129
+ #
130
+ # The <tt>:recursive</tt> option is also available for caching:
131
+ #
132
+ # stylesheet_link_tag :all, :cache => true, :recursive => true
133
+ #
134
+ # To force concatenation (even in development mode) set <tt>:concat</tt> to true. This is useful if
135
+ # you have too many stylesheets for IE to load.
136
+ #
137
+ # stylesheet_link_tag :all, :concat => true
138
+ #
139
+ def stylesheet_link_tag(*sources)
140
+ if config.use_sprockets
141
+ sprockets_stylesheet_link_tag(*sources)
142
+ else
143
+ @stylesheet_include ||= StylesheetIncludeTag.new(config, asset_paths)
144
+ @stylesheet_include.include_tag(*sources)
145
+ end
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+ end
152
+ end