Class: Juicer::Asset::Path

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

Overview

Assets are files used by CSS and JavaScript files. The Asset class provides tools for manipulating asset paths, such as rebasing, adding cache busters, and cycling asset hosts.

Asset::Path objects are most commonly created by Juicer::Asset::PathResolver#resolve which resolves include paths to file names. It is possible, however, to use the asset class directly:

Dir.pwd
#=> "/home/christian/projects/mysite/design/css"

asset = Juicer::Asset::Path.new "../images/logo.png"
asset.path
#=> "../images/logo.png"

asset.rebase("~/projects/mysite/design").path
#=> "images/logo.png"

asset.filename
#=> "/home/christian/projects/mysite/design/images/logo.png"

asset.path(:cache_buster_type => :soft)
#=> "../images/logo.png?jcb=1234567890"

asset.path(:cache_buster_type => :soft, :cache_buster => nil)
#=> "../images/logo.png?1234567890"

asset.path(:cache_buster => "bustIT")
#=> "../images/logo.png?bustIT=1234567890"

asset = Juicer::Asset::Path.new "../images/logo.png", :document_root
#=> "/home/christian/projects/mysite"

asset.absolute_path(:cache_buster_type => :hard)
#=> "/images/logo-jcb1234567890.png"

asset.absolute_path(:host => "http://localhost")
#=> "http://localhost/images/logo.png"

asset.absolute_path(:host => "http://localhost", :cache_buster_type => :hard)
#=> "http://localhost/images/logo-jcb1234567890.png"
Author

Christian Johansen ([email protected])

Copyright

Copyright © 2009 Christian Johansen

License

BSD

Constant Summary collapse

@@scheme_pattern =
%r{^([a-zA-Z]{3,5}:)?//}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, options = {}) ⇒ Path

Initialize asset at path. Accepts an optional hash of options:

:base

Base context from which asset is required. Given a path of ../images/logo.png and a :base of /project/design/css, the asset file will be assumed to live in /project/design/images/logo.png Defaults to the current directory.

:hosts

Array of host names that are served from :document_root. May also include scheme/protocol. If not, http is assumed.

:document_root

The root directory for absolute URLs (ie, the server's document root). This option is needed when resolving absolute URLs that include a hostname as well as when generating absolute paths.


84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/juicer/asset/path.rb', line 84

def initialize(path, options = {})
  @path = path
  @filename = nil
  @absolute_path = nil
  @relative_path = nil
  @path_has_host = @path =~ @@scheme_pattern
  @path_is_absolute = @path_has_host || @path =~ /^\//

  # Options
  @base = options[:base] || Dir.pwd
  @document_root = options[:document_root]
  @hosts = Juicer::Asset::Path.hosts_with_scheme(options[:hosts])
end

Instance Attribute Details

#baseObject (readonly)

Base directory to resolve relative path from, see Juicer::Asset::Path#initialize


58
59
60
# File 'lib/juicer/asset/path.rb', line 58

def base
  @base
end

#document_rootObject (readonly)

Directory served as root through a web server, see Juicer::Asset::Path#initialize


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

def document_root
  @document_root
end

#hostsObject (readonly)

Hosts served from :document_root, see Juicer::Asset::Path#initialize


61
62
63
# File 'lib/juicer/asset/path.rb', line 61

def hosts
  @hosts
end

Class Method Details

.host_with_scheme(host) ⇒ Object

Assures that a host has scheme/protocol and no trailing slash


230
231
232
233
# File 'lib/juicer/asset/path.rb', line 230

def self.host_with_scheme(host)
  return host if host.nil?
  (host !~ @@scheme_pattern ? "http://#{host}" : host).sub(/\/$/, '')
end

.hosts_with_scheme(hosts) ⇒ Object

Accepts a single host, or an array of hosts and returns an array of hosts that include scheme/protocol, and don't have trailing slash.


223
224
225
# File 'lib/juicer/asset/path.rb', line 223

def self.hosts_with_scheme(hosts)
  hosts.nil? ? [] : [hosts].flatten.collect { |host| self.host_with_scheme(host) }
end

Instance Method Details

#<=>(other) ⇒ Object


235
236
237
# File 'lib/juicer/asset/path.rb', line 235

def <=>(other)
  filename <=> other.filename
end

#absolute_path(options = {}) ⇒ Object

Returns absolute path calculated using the #document_root. Optionally accepts a hash of options:

:host

Return fully qualified URL with this host name. May include scheme/protocol. Default scheme is http.

:cache_buster

The parameter name for the cache buster.

:cache_buster_type

The kind of cache buster to add, :soft or :hard.

A cache buster will be added if either (or both) of the :cache_buster or :cache_buster_type options are provided. The default cache buster type is :soft.

Raises an ArgumentException if no document_root has been set.


114
115
116
117
118
119
120
121
122
123
124
# File 'lib/juicer/asset/path.rb', line 114

def absolute_path(options = {})
  if !@absolute_path
    # Pre-conditions
    raise ArgumentError.new("No document root set") if @document_root.nil?

    @absolute_path = filename.sub(%r{^#@document_root}, '').sub(/^\/?/, '/')
    @absolute_path = "#{Juicer::Asset::Path.host_with_scheme(options[:host])}#@absolute_path"
  end

  path_with_cache_buster(@absolute_path, options)
end

#basenameObject

Returns basename of filename on disk


201
202
203
# File 'lib/juicer/asset/path.rb', line 201

def basename
  File.basename(filename)
end

#dirnameObject

Returns basename of filename on disk


208
209
210
# File 'lib/juicer/asset/path.rb', line 208

def dirname
  File.dirname(filename)
end

#exists?Boolean

Returns true if file exists on disk

Returns:

  • (Boolean)

215
216
217
# File 'lib/juicer/asset/path.rb', line 215

def exists?
  File.exists?(filename)
end

#filenameObject

Return filename on disk. Requires the #document_root to be set if original path was an absolute one.

If asset path includes scheme/protocol and host, it can only be resolved if a match is found in #hosts. Otherwise, an exeception is raised.

Raises:

  • (ArgumentError)

168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/juicer/asset/path.rb', line 168

def filename
  return @filename if @filename

  # Pre-conditions
  raise ArgumentError.new("No document root set") if @path_is_absolute && @document_root.nil?
  raise ArgumentError.new("No hosts served from document root") if @path_has_host && @hosts.empty?

  path = strip_host(@path)
  raise ArgumentError.new("No matching host found for #{@path}") if path =~ @@scheme_pattern

  dir = @path_is_absolute ? document_root : base
  @filename = File.expand_path(File.join(dir, path))
end

#path(options = {}) ⇒ Object

Returns the original path.

Accepts an optional hash of options for cache busters:

:cache_buster

The parameter name for the cache buster.

:cache_buster_type

The kind of cache buster to add, :soft or :hard.

A cache buster will be added if either (or both) of the :cache_buster or :cache_buster_type options are provided. The default cache buster type is :soft.


157
158
159
# File 'lib/juicer/asset/path.rb', line 157

def path(options = {})
  path_with_cache_buster(@path, options)
end

#rebase(base_path) ⇒ Object

Rebase path and return a new Asset::Path object.

asset = Juicer::Asset::Path.new "../images/logo.png", :base => "/var/www/public/stylesheets"
asset2 = asset.rebase("/var/www/public")
asset2.relative_path #=> "images/logo.png"

189
190
191
192
193
194
195
196
# File 'lib/juicer/asset/path.rb', line 189

def rebase(base_path)
  path = Pathname.new(filename).relative_path_from(Pathname.new(base_path)).to_s

  Juicer::Asset::Path.new(path,
                          :base => base_path,
                          :hosts => hosts,
                          :document_root => document_root)
end

#relative_path(options = {}) ⇒ Object

Return path relative to #base

Accepts an optional hash of options for cache busters:

:cache_buster

The parameter name for the cache buster.

:cache_buster_type

The kind of cache buster to add, :soft or :hard.

A cache buster will be added if either (or both) of the :cache_buster or :cache_buster_type options are provided. The default cache buster type is :soft.


139
140
141
142
# File 'lib/juicer/asset/path.rb', line 139

def relative_path(options = {})
  @relative_path ||= Pathname.new(filename).relative_path_from(Pathname.new(base)).to_s
  path_with_cache_buster(@relative_path, options)
end