C0 code coverage information
Generated on Sat Feb 02 17:44:25 +0100 2008 with rcov 0.8.1.2
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2 # All files in this distribution are subject to the terms of the Ruby license.
3
4 require 'ramaze/helper'
5 require 'ramaze/template'
6 require 'ramaze/action'
7
8 require 'ramaze/controller/resolve'
9 require 'ramaze/controller/error'
10
11 module Ramaze
12
13 # The Controller is responsible for combining and rendering actions.
14
15 class Controller
16 include Ramaze::Helper
17 extend Ramaze::Helper
18
19 helper :redirect, :link, :file, :flash, :cgi
20
21 # Whether or not to map this controller on startup automatically
22
23 trait[:automap] ||= true
24
25 # Place to map the Controller to, this is something like '/' or '/foo'
26
27 trait[:map] ||= nil
28
29 # Modules that are excluded from the Action lookup
30
31 trait :exclude_action_modules => [Kernel, Object, PP::ObjectMixin]
32
33 # Caches patterns for the given path.
34
35 trait :pattern_cache => Hash.new{|h,k| h[k] = Controller.pattern_for(k) }
36
37 class << self
38 include Ramaze::Helper
39 extend Ramaze::Helper
40
41 # When Controller is subclassed the resulting class is placed in
42 # Global.controllers and a new trait :actions_cached is set on it.
43
44 def inherited controller
45 controller.trait :actions_cached => {}
46 controller.trait :layout => {:all => nil, :deny => Set.new}
47 Global.controllers << controller
48 if map = controller.mapping
49 Inform.dev("mapping #{map} => #{controller}")
50 Global.mapping[map] ||= controller
51 end
52 end
53
54 # called from Ramaze.startup, adds Cache.actions and Cache.patterns, walks
55 # all controllers subclassed so far and adds them to the Global.mapping if
56 # they are not assigned yet.
57
58 def startup options = {}
59 Inform.dev("found Controllers: #{Global.controllers.inspect}")
60
61 { 'Template' => Global.template_root,
62 'Public' => Global.public_root }.each do |type, path|
63 unless File.directory?(path)
64 Inform.warn("#{type} root: #{path} doesn't exist")
65 else
66 Inform.info("#{type} root: #{File.expand_path path}")
67 end
68 end
69
70 require 'ramaze/controller/main' if Global.mapping.empty?
71
72 Inform.debug("mapped Controllers: #{Global.mapping.inspect}")
73 end
74
75 # checks paths for existance and logs a warning if it doesn't exist yet.
76
77 def check_path(path, message)
78 Inform.warn(message) unless File.directory?(path)
79 end
80
81 # if trait[:automap] is set and controller is not in Global.mapping yet
82 # this will build a new default mapping-point, MainController is put
83 # at '/' by default.
84
85 def mapping
86 global_mapping = Global.mapping.invert[self]
87 return global_mapping if global_mapping
88 if ancestral_trait[:automap]
89 name = self.to_s.gsub('Controller', '').gsub('::', '/')
90 name == 'Main' ? '/' : "/#{name.snake_case}"
91 end
92 end
93
94 # Map Controller to the given syms or strings.
95 # Replaces old mappings.
96 # If you want to _add_ a mapping, just modify Global.mapping.
97
98 def map(*syms)
99 Global.mapping.delete_if{|k,v| v == self}
100
101 syms.each do |sym|
102 Global.mapping[sym.to_s] = self
103 end
104 end
105
106 # Returns the Controller at a mapped path.
107
108 def at(mapping)
109 Global.mapping[mapping.to_s]
110 end
111
112 # Define a layout for all actions on this controller
113 #
114 # Example:
115 # class Foo < Ramaze::Controller
116 # layout :foo
117 # end
118 #
119 # This defines the action :foo to be layout of the controller and will
120 # render the layout after any other action has been rendered, assigns
121 # @content to the result of the action and then goes on rendering
122 # the layout-action where @content may or may not be used, returning
123 # whatever the layout returns.
124
125 def layout(meth_or_hash)
126 if meth_or_hash.respond_to?(:to_hash)
127 meth_or_hash.each do |layout_name, *actions|
128 layout_name = R(self, layout_name) if layout_name.to_s !~ /\A\//
129 actions.flatten.each do |action|
130 trait[:layout][action.to_s] = layout_name
131 end
132 end
133 else
134 layout_name = R(self, meth_or_hash) if meth_or_hash.to_s !~ /\A\//
135 trait[:layout][:all] = layout_name || meth_or_hash
136 end
137 end
138
139 def deny_layout(*actions)
140 actions.each do |action|
141 trait[:layout][:deny] << action.to_s
142 end
143 end
144
145 # Define a template_root for Controller, returns the current template_root
146 # if no argument is given.
147 # Runs every given path through Controller::check_path
148
149 def template_root path = nil
150 if path and path = path.to_s
151 message = "#{self}.template_root is #{path} which does not exist"
152 check_path(path, message)
153 @template_root = path
154 else
155 @template_root
156 end
157 end
158
159 # This is used for template rerouting, takes action, optionally a
160 # controller and action to route to.
161 #
162 # Usage:
163 # class MainController
164 # template :index, OtherController, :list
165 # template :foo, :bar
166 #
167 # def index
168 # 'will use template from OtherController#list'
169 # end
170 #
171 # def foo
172 # 'will use template from self#bar'
173 # end
174 # end
175
176 def template(this, from, that = nil)
177 from, that = self, from unless that
178 trait "#{this}_template" => [from, that.to_s]
179 end
180
181 def engine(name)
182 name = Ramaze::Template.const_get(name)
183 rescue NameError => ex
184 Inform.warn ex
185 Inform.warn "Try to use passed engine directly"
186 ensure
187 trait :engine => name
188 end
189
190 # Return Controller of current Action
191
192 def current
193 action = Action.current
194 action.instance || action.controller
195 end
196
197 # Entering point for Dispatcher, first Controller::resolve(path) and then
198 # renders the resulting Action.
199
200 def handle path
201 action = resolve(path)
202 Inform.debug(
203 "Rendering #{action.controller}##{action.method}, params=#{action.params.inspect}, template=#{action.template}")
204 Thread.current[:controller] = action.controller
205 action.render
206 end
207 end
208
209 private
210
211 # Simplistic render, rerouting to Controller.handle(*args)
212
213 def render *args
214 self.class.handle(*args)
215 end
216 end
217 end
Generated using the rcov code coverage analysis tool for Ruby version 0.8.1.2.