aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
blob: cd0f8c88789fc8d9da32ca6d8d21e59dfe534610 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
require 'active_support/core_ext/file'
require 'action_view/helpers/asset_paths'

module ActionView
  module Helpers
    module AssetTagHelper

      class AssetPaths < ActionView::Helpers::AssetPaths #:nodoc:
        # You can enable or disable the asset tag ids cache.
        # With the cache enabled, the asset tag helper methods will make fewer
        # expensive file system calls (the default implementation checks the file
        # system timestamp). However this prevents you from modifying any asset
        # files while the server is running.
        #
        #   ActionView::Helpers::AssetTagHelper::AssetPaths.cache_asset_ids = false
        mattr_accessor :cache_asset_ids

        # Add or change an asset id in the asset id cache. This can be used
        # for SASS on Heroku.
        # :api: public
        def add_to_asset_ids_cache(source, asset_id)
          self.asset_ids_cache_guard.synchronize do
            self.asset_ids_cache[source] = asset_id
          end
        end

      private

        def rewrite_extension(source, dir, ext)
          source_ext = File.extname(source)

          source_with_ext = if source_ext.empty?
            "#{source}.#{ext}"
          elsif ext != source_ext[1..-1]
            with_ext = "#{source}.#{ext}"
            with_ext if File.exist?(File.join(config.assets_dir, dir, with_ext))
          end

          source_with_ext || source
        end

        # Break out the asset path rewrite in case plugins wish to put the asset id
        # someplace other than the query string.
        def rewrite_asset_path(source, dir)
          source = "/#{dir}/#{source}" unless source[0] == ?/
          path = config.asset_path

          if path && path.respond_to?(:call)
            return path.call(source)
          elsif path && path.is_a?(String)
            return path % [source]
          end

          asset_id = rails_asset_id(source)
          if asset_id.empty?
            source
          else
            "#{source}?#{asset_id}"
          end
        end

        mattr_accessor :asset_ids_cache
        self.asset_ids_cache = {}

        mattr_accessor :asset_ids_cache_guard
        self.asset_ids_cache_guard = Mutex.new

        # Use the RAILS_ASSET_ID environment variable or the source's
        # modification time as its cache-busting asset id.
        def rails_asset_id(source)
          if asset_id = ENV["RAILS_ASSET_ID"]
            asset_id
          else
            if self.cache_asset_ids && (asset_id = self.asset_ids_cache[source])
              asset_id
            else
              path = File.join(config.assets_dir, source)
              asset_id = File.exist?(path) ? File.mtime(path).to_i.to_s : ''

              if self.cache_asset_ids
                add_to_asset_ids_cache(source, asset_id)
              end

              asset_id
            end
          end
        end

        def rewrite_relative_url_root(source, relative_url_root)
          relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
        end

        def rewrite_host_and_protocol(source, has_request)
          source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request
          super(source, has_request)
        end
      end

    end
  end
end