Class: Tap::Controller
- Inherits:
-
Object
- Object
- Tap::Controller
- Extended by:
- Lazydoc::Attributes
- Includes:
- Rack::Utils
- Defined in:
- lib/tap/controller.rb,
lib/tap/controller/utils.rb,
lib/tap/controller/rest_routes.rb
Overview
Declaring Actions
By default all public methods in subclasses are declared as actions. You can declare a private or protected method as an action by:
-
manually adding it directly to actions
-
defining it as a public method and then call private(:method) or protected(:method)
Similarly, public method can be made non-action by actions by:
-
manually deleting it from actions
-
define it private or protected then call public(:method)
Direct Known Subclasses
Tap::Controllers::App, Tap::Controllers::Data, Tap::Controllers::Server
Defined Under Namespace
Modules: RestRoutes, Utils
Constant Summary collapse
- ServerError =
Tap::Server::ServerError
Class Attribute Summary collapse
-
.actions ⇒ Object
readonly
An array of methods that can be called as actions.
-
.default_action ⇒ Object
readonly
The default action called for the request path ‘/’.
Instance Attribute Summary collapse
-
#controller_path ⇒ Object
Returns the value of attribute controller_path.
-
#request ⇒ Object
A Rack::Request wrapping env, set during call.
-
#response ⇒ Object
A Rack::Response.
-
#server ⇒ Object
Returns the value of attribute server.
Class Method Summary collapse
-
.call(env) ⇒ Object
Instantiates self and performs call.
-
.get(variable) ⇒ Object
Gets the value of an instance variable set via set.
-
.inherited(child) ⇒ Object
Initialize instance variables on the child and inherit as necessary.
- .nest(key, controller, &block) ⇒ Object
-
.set(variable, input) ⇒ Object
Sets an instance variable for self (ie the class), short for:.
-
.set_variables ⇒ Object
An array of variables set via set.
Instance Method Summary collapse
-
#action?(action) ⇒ Boolean
Returns true if action is registered as an action for self.
-
#call(env) ⇒ Object
Routes the request to an action and returns the response.
- #dispatch(route) ⇒ Object
-
#initialize ⇒ Controller
constructor
Initializes a new instance of self.
- #module_path(path, klass = self.class) ⇒ Object
- #module_render(path, obj, options = {}) ⇒ Object
-
#redirect(uri, status = 302, headers = {}, body = "") ⇒ Object
Redirects to the specified uri.
-
#render(path, options = {}) ⇒ Object
Renders the class_file at path with the specified options.
-
#render_erb(template, options = {}, filename = nil) ⇒ Object
Renders the specified template as ERB using the options.
-
#render_layout(layout, content) ⇒ Object
Renders the specified layout with content as a local variable.
-
#route ⇒ Object
Returns the action, args, and extname for the request.path_info.
- #template_path(path) ⇒ Object
-
#uri(action = nil, params = {}) ⇒ Object
Returns a uri to the specified action on self.
Constructor Details
#initialize ⇒ Controller
Initializes a new instance of self.
163 164 165 |
# File 'lib/tap/controller.rb', line 163 def initialize @request = @response = @server = @controller_path = nil end |
Class Attribute Details
.actions ⇒ Object (readonly)
An array of methods that can be called as actions. Actions must be stored as symbols. Actions are inherited.
43 44 45 |
# File 'lib/tap/controller.rb', line 43 def actions @actions end |
.default_action ⇒ Object (readonly)
The default action called for the request path ‘/’
46 47 48 |
# File 'lib/tap/controller.rb', line 46 def default_action @default_action end |
Instance Attribute Details
#controller_path ⇒ Object
Returns the value of attribute controller_path.
152 153 154 |
# File 'lib/tap/controller.rb', line 152 def controller_path @controller_path end |
#request ⇒ Object
A Rack::Request wrapping env, set during call.
155 156 157 |
# File 'lib/tap/controller.rb', line 155 def request @request end |
#response ⇒ Object
A Rack::Response. If the action returns a string, it will be written to response and response will be returned by call. Otherwise, call returns the action result and response is ignored.
160 161 162 |
# File 'lib/tap/controller.rb', line 160 def response @response end |
#server ⇒ Object
Returns the value of attribute server.
150 151 152 |
# File 'lib/tap/controller.rb', line 150 def server @server end |
Class Method Details
.call(env) ⇒ Object
Instantiates self and performs call.
49 50 51 |
# File 'lib/tap/controller.rb', line 49 def call(env) new.call(env) end |
.get(variable) ⇒ Object
Gets the value of an instance variable set via set. Returns nil for variables that have not been set through set.
70 71 72 73 |
# File 'lib/tap/controller.rb', line 70 def get(variable) return nil unless set_variables.include?(variable) instance_variable_get("@#{variable}") end |
.inherited(child) ⇒ Object
Initialize instance variables on the child and inherit as necessary.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/tap/controller.rb', line 25 def inherited(child) # :nodoc: super unless child.instance_variable_defined?(:@source_file) caller[0] =~ Lazydoc::CALLER_REGEXP child.instance_variable_set(:@source_file, File.($1)) end set_variables.each do |variable| child.set(variable, get(variable)) end child.set(:actions, actions.dup) child.set(:define_action, true) end |
.nest(key, controller, &block) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/tap/controller.rb', line 80 def nest(key, controller, &block) # generate a subclass if anything gets overridden if block_given? controller = Class.new(controller) controller.class_eval(&block) end # this check prevents a warning in cases where the nesting # class defines the nested class const_name = key.to_s.camelize unless const_defined?(const_name) && const_get(const_name) == subclass const_set(const_name, controller) end define_method(key) do |*args| instance = controller.new instance.server = server instance.controller_path = controller_path ? "#{controller_path}/#{key}" : key instance.request = request instance.response = response instance.dispatch(args) end end |
.set(variable, input) ⇒ Object
Sets an instance variable for self (ie the class), short for:
instance_variable_set(:@attribute, input)
These variables are meaningful to a default Tap::Controller and will be inherited by subclasses:
actions:: sets actions
default_action:: the default action (:index)
63 64 65 66 |
# File 'lib/tap/controller.rb', line 63 def set(variable, input) set_variables << variable instance_variable_set("@#{variable}", input) end |
.set_variables ⇒ Object
An array of variables set via set. set_variables are inherited.
76 77 78 |
# File 'lib/tap/controller.rb', line 76 def set_variables @set_variables ||= [] end |
Instance Method Details
#action?(action) ⇒ Boolean
Returns true if action is registered as an action for self.
168 169 170 |
# File 'lib/tap/controller.rb', line 168 def action?(action) self.class.actions.include?(action.to_sym) end |
#call(env) ⇒ Object
Routes the request to an action and returns the response. Routing is simple and fixed (see route):
route calls
/ default_action (ie 'index')
/action/*args action(*args)
If the action returns a string, it will be written to response. Otherwise, call returns the result of action. This allows actions like:
class ActionsController < Tap::Controller
def simple
"html body"
end
def standard
response["Content-Type"] = "text/plain"
response << "text"
response.finish
end
def custom
[200, {"Content-Type" => "text/plain"}, ["text"]]
end
end
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/tap/controller.rb', line 228 def call(env) @server = env['tap.server'] @controller_path = env['tap.controller_path'] @request = Rack::Request.new(env) @response = Rack::Response.new case result = dispatch(route) when String response.write result response.finish when nil response.finish else result end end |
#dispatch(route) ⇒ Object
261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/tap/controller.rb', line 261 def dispatch(route) action, *args = route if action == nil || action == "" action = self.class.default_action end unless action?(action) raise ServerError.new("404 Error: page not found", 404) end send(action, *args) end |
#module_path(path, klass = self.class) ⇒ Object
198 199 200 |
# File 'lib/tap/controller.rb', line 198 def module_path(path, klass=self.class) server.env.module_path(:views, klass.ancestors, path) {|file| File.file?(file) } end |
#module_render(path, obj, options = {}) ⇒ Object
355 356 357 358 359 360 361 362 363 |
# File 'lib/tap/controller.rb', line 355 def module_render(path, obj, ={}) obj = obj.class unless obj.kind_of?(Module) [:file] = module_path(path, obj) || module_path(path) locals = [:locals] ||= {} locals[:obj] ||= obj render end |
#redirect(uri, status = 302, headers = {}, body = "") ⇒ Object
Redirects to the specified uri.
366 367 368 369 370 371 372 373 |
# File 'lib/tap/controller.rb', line 366 def redirect(uri, status=302, headers={}, body="") response.status = status response.headers.merge!(headers) response.body = body response['Location'] = [uri] response.finish end |
#render(path, options = {}) ⇒ Object
Renders the class_file at path with the specified options. Path can be omitted if options specifies an alternate path to render. Options:
template:: renders the template relative to the template directory
file:: renders the specified file
layout:: renders with the specified layout, or default_layout if true
locals:: a hash of local variables used in the template
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/tap/controller.rb', line 283 def render(path, ={}) , path = path, nil if path.kind_of?(Hash) # lookup template template_path = case when [:file] [:file] when [:template] self.template_path([:template]) else self.module_path(path) end unless template_path raise "could not find template: (path: #{path.inspect}, file: #{[:file].inspect}, template: #{[:template].inspect})" end # render template template = File.read(template_path) content = render_erb(template, , template_path) # render layout render_layout([:layout], content) end |
#render_erb(template, options = {}, filename = nil) ⇒ Object
Renders the specified template as ERB using the options. Options:
locals:: a hash of local variables used in the template
The filename used to identify errors in an erb template to a specific file and is completely options (but handy).
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/tap/controller.rb', line 339 def render_erb(template, ={}, filename=nil) # assign locals to the render binding # this almost surely may be optimized... locals = [:locals] binding = render_erb_binding locals.each_pair do |key, value| @assignment_value = value eval("#{key} = remove_instance_variable(:@assignment_value)", binding) end if locals erb = ERB.new(template, nil, "<>") erb.filename = filename erb.result(binding) end |
#render_layout(layout, content) ⇒ Object
Renders the specified layout with content as a local variable. If layout is true, the class default_layout will be rendered. Returns content if no layout is specified.
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/tap/controller.rb', line 311 def render_layout(layout, content) return content unless layout if layout == true layout = self.class.get(:default_layout) end if layout.kind_of?(Hash) locals = layout[:locals] ||= {} if locals.has_key?(:content) raise "layout already has local content assigned: #{layout.inspect}" end locals[:content] = content else layout = {:template => layout, :locals => {:content => content}} end render(layout) end |
#route ⇒ Object
Returns the action, args, and extname for the request.path_info. Routing is simple and fixed:
route returns
/ [:index, []]
/action/*args [:action, args]
The action and args are unescaped by route. An alternate default action may be specified using set. Override this method in subclasses for fancier routes.
256 257 258 259 |
# File 'lib/tap/controller.rb', line 256 def route blank, *route = request.path_info.split("/").collect {|arg| unescape(arg) } route end |
#template_path(path) ⇒ Object
194 195 196 |
# File 'lib/tap/controller.rb', line 194 def template_path(path) server.env.path(:views, path) {|file| File.file?(file) } end |
#uri(action = nil, params = {}) ⇒ Object
Returns a uri to the specified action on self.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/tap/controller.rb', line 173 def uri(action=nil, params={}) uri = [] if controller_path uri << '/' uri << controller_path end if action uri << '/' uri << action end unless params.empty? uri << '?' uri << build_query(params) end uri.join end |