require 'set' module SignedForm class Digestor attr_accessor :view_paths def initialize(template) @view_paths = Set.new @views = Set.new self << template end def <<(template) virtual_path = get_virtual_path(template) raise Errors::UnableToDigest, "Unable to get virtual path from template" unless virtual_path @views << virtual_path @view_paths += template.view_paths.map(&:to_s) @digest = nil rescue NoMethodError raise Errors::UnableToDigest, "Unable get view paths from template" end def marshal_dump [@views.to_a, to_s] end def marshal_load(input) @views, @digest = input @view_paths = [] @digest.taint end def to_s @digest ||= SignedForm.digest_store.fetch(@views.sort.join(':')) { hash_files(glob_files) } end alias_method :digest, :to_s def refresh @digest = nil end private def glob_files globbed_files = [] view_paths.each do |path| @views.each { |view| globbed_files += Dir["#{path}/#{view}.*"] } end globbed_files end def hash_files(files) raise Errors::UnableToDigest, "No files to digest" if files.empty? md5 = Digest::MD5.new files.sort.each do |entry| File.open(entry) { |f| md5 << f.read } end md5.to_s end def get_virtual_path(template) template.respond_to?(:virtual_path) ? template.virtual_path : template.instance_variable_get(:@virtual_path) end end end