Class: Ramaze::Asset::FileGroup
- Inherits:
-
Object
- Object
- Ramaze::Asset::FileGroup
- Defined in:
- lib/ramaze/asset/file_group.rb
Overview
Ramaze::Asset::FileGroup is used to group a set of files of the same type, such as Javascript files, together. The HTML for these files can be generated as well as a minified version of all the files.
## Creating File Groups
Ramaze::Asset comes with two file groups that are capable of processing Javascript and CSS files. If you need to have a file group for Coffeescript, Less or other files is quite easy to add these yourself. First you must create a class that extends Ramaze::Asset::FileGroup:
class Less < Ramaze::Asset::FileGroup
end
It’s important that you define the correct file extensions for your file group. Without this Ramaze::Asset will not be able to find the files for you (unless they have an extension specified) and the minified file will end up not having an extension. Setting an extension can be done by calling the class method “extension()“. This method has two parameters, the first one is the extension of the source file, the second the extension for the minified file. In case of Less this would result in the following:
class Less < Ramaze::Asset::FileGroup
extension '.less', '.css'
end
The next step is to define your own minify() and html_tag() methods. If you don’t define these methods they’ll raise an error and most likely break things.
class Less < Ramaze::Asset::FileGroup
extension '.less', '.css'
def minify(input)
end
def html_tag(gestalt, path)
end
end
The minify() method should return a string containing the minified data. The html_tag() method uses an instance of Ramaze::Gestalt to build a single tag for a given (relative) path.
A full example of Less looks like the following:
require 'tempfile'
class Less < Ramaze::Asset::FileGroup
extension '.less', '.css'
# +input+ contains the raw Less data. The command line tool only
# accepts files so this data has to be written to a temp file.
def minify(input)
file = Tempfile.new('less')
file.write(input)
file.rewind
minified = `lessc #{file.path} -x`
file.close(true)
return minified
end
def html_tag(gestalt, path)
gestalt.link(
:rel => 'stylesheet',
:href => path,
:type => 'text/css'
)
end
end
Note that it’s important to remember that when dealing with files that have to be compiled, such as Less and Coffeescript files, setting :minify to false will not work. Without setting this option to true the minify() method will never be called and thus the raw Less/Coffeescript file would be served.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#files ⇒ Object
Array containing all the files that belong to this group, including their files extensions.
-
#options ⇒ Object
readonly
Hash containing all the options for the file group.
Class Method Summary collapse
-
.extension(source_ext, minified_ext = nil) ⇒ Object
Sets the file extensions for the current class.
Instance Method Summary collapse
-
#build ⇒ Object
When the :minify option is set to true this method will merge all files, minify them and cache them in the :cache_path directory.
-
#build_html ⇒ String
Builds the HTML tags for all the current files.
-
#extension ⇒ String
Returns the extension of the current file group.
-
#html_tag(gestalt, path) ⇒ Object
Builds the HTML tag for a single file using Ramaze::Gestalt.
-
#initialize(files, options = {}) ⇒ FileGroup
constructor
Creates a new instance of the file group and prepares it.
-
#minify(input) ⇒ Object
Minifies a single file.
Constructor Details
#initialize(files, options = {}) ⇒ FileGroup
Creates a new instance of the file group and prepares it.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/ramaze/asset/file_group.rb', line 153 def initialize(files, = {}) @minified = false @files = files @options = { :minify => false, :name => nil, :paths => [], :cache_path => [] }.merge() if @options[:paths].empty? raise( Ramaze::Asset::AssetError, 'No public directories were specified' ) end if !File.directory?(@options[:cache_path]) raise( Ramaze::Asset::AssetError, "The directory #{@options[:cache_path]} does not exist" ) end if extension.nil? raise( Ramaze::Asset::AssetError, 'You need to specify an extension' ) end prepare_files # When :minify is set :name should also be set. if @options[:minify] === true and @options[:name].nil? @options[:name] = @files.map { |file| file }.join() @options[:name] = Digest::SHA1.new.hexdigest(@options[:name]) end if !@options[:name].nil? @options[:name] += extension[:minified] end end |
Instance Attribute Details
#files ⇒ Object
Array containing all the files that belong to this group, including their files extensions.
99 100 101 |
# File 'lib/ramaze/asset/file_group.rb', line 99 def files @files end |
#options ⇒ Object (readonly)
Hash containing all the options for the file group.
102 103 104 |
# File 'lib/ramaze/asset/file_group.rb', line 102 def @options end |
Class Method Details
.extension(source_ext, minified_ext = nil) ⇒ Object
Sets the file extensions for the current class. These extensions should start with a dot. If the minified extension is not specified it will be generated by adding a “.min” suffix followed by the source extension. If the source extension is “.css” the minified extension would in this case be “.min.css”.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/ramaze/asset/file_group.rb', line 119 def self.extension(source_ext, minified_ext = nil) if minified_ext.nil? minified_ext = '.min' + source_ext end if source_ext[0] != '.' or minified_ext[0] != '.' raise( Ramaze::Asset::AssetError, 'Extensions should start with a dot' ) end self.instance_variable_set( :@extension, {:source => source_ext, :minified => minified_ext} ) end |
Instance Method Details
#build ⇒ Object
When the :minify option is set to true this method will merge all files, minify them and cache them in the :cache_path directory.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/ramaze/asset/file_group.rb', line 215 def build return if @options[:minify] != true cache_path = File.join( @options[:cache_path], @options[:name] ) # Minify the file in a sub process so that memory leaks (or just general # increases of memory usage) don't affect the master process. pid = Process.fork do processed = [] file_paths = [] minified = '' write = true # Try to find the paths to the files. @options[:paths].each do |directory| @files.each do |file| path = File.join(directory, file) # Only add the file to the list if it hasn't already been added. if File.exist?(path) and !processed.include?(file) file_paths.push(path) processed.push(file) end end end file_paths.each do |file| minified += minify(File.read(file, File.size(file))) end # Check if the file already exists. If this is the cache a hash of # both files is generated and compared. If it's different the file has # to be re-created. if File.exist?(cache_path) old_hash = Digest::SHA1.new.hexdigest(minified) new_hash = Digest::SHA1.new.hexdigest( File.read(cache_path, File.size(cache_path)) ) if old_hash === new_hash write = false end end if write === true File.open(cache_path, 'w') do |handle| handle.write(minified) handle.close end end # Don't call any at_exit() hooks, they're not needed in this process. Kernel.exit! end Process.waitpid(pid) # Make sure the cache file is present if !File.size?(cache_path) raise( Ramaze::Asset::AssetError, "The cache file #{cache_path} could not be created" ) end @minified = true end |
#build_html ⇒ String
Builds the HTML tags for all the current files.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/ramaze/asset/file_group.rb', line 293 def build_html prefix = '/' if @options[:minify] === true and @minified === true # Get the relative path to the cache directory from one of the public # directories. @options[:paths].each do |path| path = @options[:cache_path].gsub(path, '') if path != @options[:cache_path] and !path.empty? prefix += path break end end files = [('/' + @options[:name]).squeeze('/')] else files = @files end # Let's make sure the URLs are actually pointing to the cached # directory. files.each_with_index do |file, index| files[index] = "#{prefix}/#{file}".squeeze('/') end g = Ramaze::Gestalt.new files.each { |file| html_tag(g, file) } return g.to_s end |
#extension ⇒ String
Returns the extension of the current file group.
204 205 206 |
# File 'lib/ramaze/asset/file_group.rb', line 204 def extension return self.class.instance_variable_get(:@extension) end |
#html_tag(gestalt, path) ⇒ Object
Builds the HTML tag for a single file using Ramaze::Gestalt.
353 354 355 356 357 358 |
# File 'lib/ramaze/asset/file_group.rb', line 353 def html_tag(gestalt, path) raise( NotImplementedError, 'You need to define your own build_html instance method' ) end |
#minify(input) ⇒ Object
Minifies a single file.
335 336 337 338 339 340 |
# File 'lib/ramaze/asset/file_group.rb', line 335 def minify(input) raise( NotImplementedError, 'You need to define your own minify() instance method' ) end |