Class: AssetID::Asset

Inherits:
Object
  • Object
show all
Defined in:
lib/asset_id/asset.rb

Constant Summary collapse

DEFAULT_ASSET_PATHS =
['favicon.ico', 'images', 'javascripts', 'stylesheets']
DEFAULT_GZIP_TYPES =
['text/css', 'application/javascript']
@@asset_paths =
DEFAULT_ASSET_PATHS
@@gzip_types =
DEFAULT_GZIP_TYPES
@@debug =
false
@@nocache =
false

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Asset

Returns a new instance of Asset.



59
60
61
62
# File 'lib/asset_id/asset.rb', line 59

def initialize(path)
  @path = path
  @path = absolute_path
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



57
58
59
# File 'lib/asset_id/asset.rb', line 57

def path
  @path
end

Class Method Details

.asset_pathsObject



23
24
25
# File 'lib/asset_id/asset.rb', line 23

def self.asset_paths
  @@asset_paths
end

.asset_paths=(paths) ⇒ Object



31
32
33
# File 'lib/asset_id/asset.rb', line 31

def self.asset_paths=(paths)
  @@asset_paths = paths
end

.find(paths = Asset.asset_paths) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/asset_id/asset.rb', line 39

def self.find(paths=Asset.asset_paths)
  paths.inject([]) {|assets, path|
    path = File.join Rails.root, 'public', path
    a = Asset.new(path)
    assets << a if a.is_file? and !a.cache_hit?
    assets += Dir.glob(path+'/**/*').inject([]) {|m, file|
      a = Asset.new(file); m << a if a.is_file? and !a.cache_hit?; m 
    }
  }
end

.fingerprint(path) ⇒ Object



50
51
52
53
54
55
# File 'lib/asset_id/asset.rb', line 50

def self.fingerprint(path)
  asset = Asset.new(path)
  hit = Cache.get(asset)
  return hit[:fingerprint] if hit
  return asset.fingerprint
end

.gzip_typesObject



27
28
29
# File 'lib/asset_id/asset.rb', line 27

def self.gzip_types
  @@gzip_types
end

.gzip_types=(types) ⇒ Object



35
36
37
# File 'lib/asset_id/asset.rb', line 35

def self.gzip_types=(types)
  @@gzip_types = types
end

.init(options) ⇒ Object



18
19
20
21
# File 'lib/asset_id/asset.rb', line 18

def self.init(options)
  @@debug = options[:debug] if options[:debug]
  @@nocache = options[:nocache] if options[:nocache]
end

Instance Method Details

#absolute_pathObject



68
69
70
# File 'lib/asset_id/asset.rb', line 68

def absolute_path
  path =~ /#{path_prefix}/ ? path : File.join(path_prefix, path)
end

#cache_headersObject



139
140
141
# File 'lib/asset_id/asset.rb', line 139

def cache_headers
  {'Expires' => expiry_date, 'Cache-Control' => 'public'} # 1 year expiry
end

#cache_hit?Boolean

Returns:

  • (Boolean)


151
152
153
154
155
# File 'lib/asset_id/asset.rb', line 151

def cache_hit?
  return false if @@nocache or Cache.miss? self
  puts "AssetID: #{relative_path} - Cache Hit" 
  return true 
end

#css?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/asset_id/asset.rb', line 97

def css?
  mime_type == 'text/css'
end

#dataObject



80
81
82
# File 'lib/asset_id/asset.rb', line 80

def data
  @data ||= File.read(path)
end

#expiry_dateObject



135
136
137
# File 'lib/asset_id/asset.rb', line 135

def expiry_date
  @expiry_date ||= (Time.now + (60*60*24*365)).httpdate
end

#fingerprintObject



88
89
90
91
# File 'lib/asset_id/asset.rb', line 88

def fingerprint
  p = relative_path
  File.join File.dirname(p), "#{File.basename(p, File.extname(p))}-id-#{md5}#{File.extname(p)}"
end

#gzip!Object



126
127
128
129
130
131
132
133
# File 'lib/asset_id/asset.rb', line 126

def gzip!
  # adapted from https://github.com/blakink/asset_id
  @data = returning StringIO.open('', 'w') do |gz_data|
    gz = Zlib::GzipWriter.new(gz_data, nil, nil)
    gz.write(data)
    gz.close
  end.string
end

#gzip_headersObject



143
144
145
# File 'lib/asset_id/asset.rb', line 143

def gzip_headers
  {'Content-Encoding' => 'gzip', 'Vary' => 'Accept-Encoding'}
end

#gzip_type?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/asset_id/asset.rb', line 76

def gzip_type?
  Asset.gzip_types.include? mime_type
end

#is_file?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'lib/asset_id/asset.rb', line 147

def is_file?
  File.exists? absolute_path and !File.directory? absolute_path
end

#md5Object



84
85
86
# File 'lib/asset_id/asset.rb', line 84

def md5
  @digest ||= Digest::MD5.hexdigest(data)
end

#mime_typeObject



93
94
95
# File 'lib/asset_id/asset.rb', line 93

def mime_type
  MIME::Types.of(path).first.to_s
end

#path_prefixObject



64
65
66
# File 'lib/asset_id/asset.rb', line 64

def path_prefix
  File.join Rails.root, 'public'
end

#relative_pathObject



72
73
74
# File 'lib/asset_id/asset.rb', line 72

def relative_path
  path.gsub(path_prefix, '')
end

#replace_css_images!(options = {}) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/asset_id/asset.rb', line 101

def replace_css_images!(options={})
  options[:prefix] ||= ''
  # adapted from https://github.com/blakink/asset_id
  data.gsub! /url\((?:"([^"]*)"|'([^']*)'|([^)]*))\)/mi do |match|
    begin
      # $1 is the double quoted string, $2 is single quoted, $3 is no quotes
      uri = ($1 || $2 || $3).to_s.strip
      uri.gsub!(/^\.\.\//, '/')
      
      # if the uri appears to begin with a protocol then the asset isn't on the local filesystem
      if uri =~ /[a-z]+:\/\//i
        "url(#{uri})"
      else
        asset = Asset.new(uri)
        # TODO: Check the referenced asset is in the asset_paths
        puts "  - Changing CSS URI #{uri} to #{options[:prefix]}#{asset.fingerprint}" if @@debug
        "url(#{options[:prefix]}#{asset.fingerprint})"
      end
    rescue Errno::ENOENT => e
      puts "  - Warning: #{uri} not found" if @@debug
      "url(#{uri})"
    end
  end
end