File: view.rb

package info (click to toggle)
libinnate-ruby 2010.07-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 812 kB
  • ctags: 621
  • sloc: ruby: 4,242; makefile: 2
file content (101 lines) | stat: -rw-r--r-- 3,045 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
module Innate

  # This is a container module for wrappers of templating engines and handles
  # lazy requiring of needed engines.
  module View
    include Optioned

    ENGINE, TEMP = {}, {}

    options.dsl do
      o "Cache compiled templates",
        :cache, true

      o "Cache template files after they're read to prevent additional filesystem calls",
        :read_cache, false
    end

    # In order to be able to render actions without running
    # Innate::setup_dependencies we have to add the cache here already.
    Cache.add(:view)

    module_function

    def compile(string)
      return yield(string.to_s) unless View.options.cache
      string = string.to_s
      checksum = Digest::MD5.hexdigest(string)
      Cache.view[checksum] ||= yield(string)
    end

    def exts_of(engine)
      name = engine.to_s
      ENGINE.reject{|ext, klass| klass != name }.keys
    end

    # Try to obtain given engine by its registered name.
    def get(engine)
      if klass = TEMP[engine]
        return klass
      elsif klass = ENGINE[engine]
        TEMP[engine] = obtain(klass)
      else
        TEMP[engine] = obtain(engine, View)
      end
    end

    # We need to put this in a Mutex because simultanous calls for the same
    # class will cause race conditions and one call may return the wrong class
    # on the first request (before TEMP is set).
    # No mutex is used in Fiber environment, see Innate::State and subclasses.
    def obtain(klass, root = Object)
      Innate.sync do
        view_name = /^#{klass.to_s.downcase.dup.delete('_')}$/i
        if view = View.constants.grep(view_name).first
          root.const_get(view)
        else
          raise(NameError, "View #{klass} not found")
        end
      end
    end

    # Reads the specified view template from the filesystem. When the read_cache
    # option is enabled, templates will be cached to prevent unnecessary
    # filesystem reads in the future.
    #
    # @example usage
    #
    #   View.read('some/file.xhtml')
    #
    # @param [#to_str] view
    #
    # @api private
    # @see Action#render
    def read(view)
      return Cache.view[view] ||= ::File.read(view) if View.options.read_cache
      ::File.read(view)
    end

    # Register given templating engine wrapper and extensions for later usage.
    #
    # +name+ : the class name of the templating engine wrapper
    # +exts+ : any number of arguments will be turned into strings via #to_s
    #          that indicate which filename-extensions the templates may have.
    def register(klass, *exts)
      exts.each do |ext|
        ext = ext.to_s
        engine = ENGINE[ext]
        Log.warn("overwriting %p, was set to %p" % [ext, engine]) if engine
        ENGINE[ext] = klass
      end
    end

    autoload :None,   'innate/view/none'
    autoload :ERB,    'innate/view/erb'
    autoload :Etanni, 'innate/view/etanni'

    register 'Innate::View::None',   :css, :html, :htm
    register 'Innate::View::ERB',    :erb
    register 'Innate::View::Etanni', :xhtml
  end
end