index.rb 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. require 'sprockets/base'
  2. module Sprockets
  3. # `Index` is a special cached version of `Environment`.
  4. #
  5. # The expection is that all of its file system methods are cached
  6. # for the instances lifetime. This makes `Index` much faster. This
  7. # behavior is ideal in production environments where the file system
  8. # is immutable.
  9. #
  10. # `Index` should not be initialized directly. Instead use
  11. # `Environment#index`.
  12. class Index < Base
  13. def initialize(environment)
  14. @environment = environment
  15. # Copy environment attributes
  16. @logger = environment.logger
  17. @context_class = environment.context_class
  18. @cache = environment.cache
  19. @trail = environment.trail.index
  20. @digest = environment.digest
  21. @digest_class = environment.digest_class
  22. @version = environment.version
  23. @mime_types = environment.mime_types
  24. @engines = environment.engines
  25. @preprocessors = environment.preprocessors
  26. @postprocessors = environment.postprocessors
  27. @bundle_processors = environment.bundle_processors
  28. # Initialize caches
  29. @assets = {}
  30. @digests = {}
  31. end
  32. # No-op return self as index
  33. def index
  34. self
  35. end
  36. # Cache calls to `file_digest`
  37. def file_digest(pathname)
  38. key = pathname.to_s
  39. if @digests.key?(key)
  40. @digests[key]
  41. else
  42. @digests[key] = super
  43. end
  44. end
  45. # Cache `find_asset` calls
  46. def find_asset(path, options = {})
  47. options[:bundle] = true unless options.key?(:bundle)
  48. if asset = @assets[cache_key_for(path, options)]
  49. asset
  50. elsif asset = super
  51. logical_path_cache_key = cache_key_for(path, options)
  52. full_path_cache_key = cache_key_for(asset.pathname, options)
  53. # Cache on Index
  54. @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
  55. # Push cache upstream to Environment
  56. @environment.instance_eval do
  57. @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
  58. end
  59. asset
  60. end
  61. end
  62. protected
  63. # Index is immutable, any methods that try to clear the cache
  64. # should bomb.
  65. def expire_index!
  66. raise TypeError, "can't modify immutable index"
  67. end
  68. # Cache asset building in memory and in persisted cache.
  69. def build_asset(path, pathname, options)
  70. # Memory cache
  71. key = cache_key_for(pathname, options)
  72. if @assets.key?(key)
  73. @assets[key]
  74. else
  75. @assets[key] = begin
  76. # Persisted cache
  77. cache_asset(key) do
  78. super
  79. end
  80. end
  81. end
  82. end
  83. end
  84. end