Class: Mack::Controller::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/sea_level/controller_base.rb

Overview

All controllers in a Mack application have to extend this class. I’ll be honest, if they don’t extend this class then, well, things just won’t work very well!

Example:

class MyAwesomeController < Mack::Controller::Base
  def index
    render(:text => "Hello World!")
  end
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request, response, cookies) ⇒ Base

Returns a new instance of Base.



26
27
28
29
30
31
32
33
34
35
# File 'lib/sea_level/controller_base.rb', line 26

def initialize(request, response, cookies)
  @request = request
  @response = response
  @render_options = {}
  @render_performed = false
  @controller_name = params(:controller)
  @action_name = params(:action)
  @cookies = cookies
  @wants_list = []
end

Instance Attribute Details

#action_nameObject (readonly)

The name of the action being requested.



22
23
24
# File 'lib/sea_level/controller_base.rb', line 22

def action_name
  @action_name
end

#controller_nameObject (readonly)

The ‘underscore’ version of the controller requested. Example: ‘my_awesome_controller’



20
21
22
# File 'lib/sea_level/controller_base.rb', line 20

def controller_name
  @controller_name
end

#cookiesObject (readonly)

See Mack::CookieJar for more information.



24
25
26
# File 'lib/sea_level/controller_base.rb', line 24

def cookies
  @cookies
end

#requestObject (readonly)

See Mack::Request for more information.



16
17
18
# File 'lib/sea_level/controller_base.rb', line 16

def request
  @request
end

#responseObject (readonly)

See Mack::Response for more information.



18
19
20
# File 'lib/sea_level/controller_base.rb', line 18

def response
  @response
end

Class Method Details

.add_filter(type, meth, options) ⇒ Object

:nodoc:



322
323
324
# File 'lib/sea_level/controller_base.rb', line 322

def add_filter(type, meth, options) # :nodoc:
  controller_filters[type.to_sym] << Mack::Controller::Filter.new(meth, options)
end

.after_filter(meth, options = {}) ⇒ Object

See Mack::Controller::Filter for more information.



313
314
315
# File 'lib/sea_level/controller_base.rb', line 313

def after_filter(meth, options = {})
  add_filter(:after, meth, options)
end

.after_render_filter(meth, options = {}) ⇒ Object

See Mack::Controller::Filter for more information.



318
319
320
# File 'lib/sea_level/controller_base.rb', line 318

def after_render_filter(meth, options = {})
  add_filter(:after_render, meth, options)
end

.before_filter(meth, options = {}) ⇒ Object

See Mack::Controller::Filter for more information.



308
309
310
# File 'lib/sea_level/controller_base.rb', line 308

def before_filter(meth, options = {})
  add_filter(:before, meth, options)
end

.controller_filtersObject

:nodoc:



326
327
328
329
# File 'lib/sea_level/controller_base.rb', line 326

def controller_filters # :nodoc:
  @controller_filters = {:before => [], :after => [], :after_render => []} unless @controller_filters
  @controller_filters
end

.layout(lay) ⇒ Object

Sets a layout to be used by a particular controller.

Example:

class MyAwesomeController < Mack::Controller::Base
  # Sets all actions to use: "#{MACK_ROOT}/app/views/layouts/dark.html.erb" as they're layout.
  layout :dark

  def index
    # Sets this action to use: "#{MACK_ROOT}/app/views/layouts/bright.html.erb" as it's layout.
    render(:text => "Welcome...", :layout => :bright)
  end

  def index
    # This will no use a layout.
    render(:text => "Welcome...", :layout => false)
  end
end

The default layout is “#MACK_ROOT/app/views/layouts/application.html.erb”.

If a layout is specified, and it doesn’t exist a Mack::Errors::UnknownLayout error will be raised.



352
353
354
355
356
357
358
# File 'lib/sea_level/controller_base.rb', line 352

def layout(lay)
  self.class_eval do
    define_method(:layout) do
      lay
    end
  end
end

Instance Method Details

#loggerObject

Gives access to the MACK_DEFAULT_LOGGER.



238
239
240
# File 'lib/sea_level/controller_base.rb', line 238

def logger
  MACK_DEFAULT_LOGGER
end

#params(key) ⇒ Object

Gives access to all the parameters for this request.



38
39
40
# File 'lib/sea_level/controller_base.rb', line 38

def params(key)
  self.request.params(key)
end

#redirect_to(url, options = {}) ⇒ Object

This will redirect the request to the specified url. A default status of 302, Moved Temporarily, is set if no status is specified. A simple HTML page is rendered in case the redirect does not occur. A server side redirect is also possible by using the option :server_side => true. When a server side redirect occurs the url must be a ‘local’ url, not an external url. The ‘original’ url of the request will NOT change.

Raises:

  • (Rack::ForwardRequest)


194
195
196
197
198
199
200
# File 'lib/sea_level/controller_base.rb', line 194

def redirect_to(url, options = {})
  options = {:status => 302}.merge(options)
  raise Rack::ForwardRequest.new(url) if options[:server_side]
  response.status = options[:status]
  response[:location] = url
  render(:text => redirect_html(request.path_info, url, options[:status]))
end

#render(options = {:action => self.action_name}) ⇒ Object

This method can be called from within an action. This ‘registers’ the render that you would like to happen once the action is completed.

It’s important to note that calling render in an action does NOT end the processing of the action. The action will continue to process unless you explicity put ‘return’ before the render call.

If you call render twice in an action then a Mack::Errors::DoubleRender error will be thrown.

An implicit render will happen if one is not specified in the action.

Only :action and :text will get layouts wrapped around them.

Examples:

class MyAwesomeController < Mack::Controller::Base
  # This will render the text 'Hello World!' to the screen.
  def index
    render(:text => "Hello World!")
  end

  # This will render MACK_ROOT/views/my_awesome_controller/foo.html.erb
  def show
    render(:action => :foo)
  end

  # This will raise a Mack::Errors::DoubleRender error.
  def edit
    render(:text => "Hello World!")
    render(:action => :foo)
  end

  # This will render MACK_ROOT/views/my_awesome_controller/delete.html.erb
  def delete
  end

  # This will render the text 'Hello World!' to the screen. Assuming that
  # there is no file: MACK_ROOT/views/my_awesome_controller/update.html.erb
  # The reason for this is if the view for the action doesn't exist, and the
  # last thing returned from the action is a String, that string will be returned.
  def update
    "Hello World!"
  end

  # This will raise a Mack::Errors::InvalidRenderType error. Assuming that
  # there is no file: MACK_ROOT/views/my_awesome_controller/create.html.erb
  def create
    @user = User.find(1)
  end

  # This will raise a Errno::ENOENT error. Assuming that
  # there is no file: MACK_ROOT/views/my_awesome_controller/bar.html.erb
  def bar
    render(:action => "bar")
  end

  # This will render a file from the public directory. Files served from the
  # public directory do NOT get layouts. The default file extension for files
  # served from the public directory is .html. This can be overridden with the
  # :ext => ".<ext>" option.
  def show_public_file
    render(:public => "my/files/foo")
  end

  # This will render a file from the public directory. Files served from the
  # public directory do NOT get layouts. The default file extension for files
  # served from the public directory is .html. This can be overridden with the
  # :ext => ".<ext>" option. 
  def show_public_xml_file
    render(:public => "my/files/foo", :ext => ".xml")
  end

  # This will render a partial. In this case it will look for:
  # MACK_ROOT/views/my_awesome_controller/_latest_news.html.erb
  # Partials do NOT get wrapped in layouts.
  def latest_news
    render(:partial => :latest_news)
  end

  # This will render a partial. In this case it will look for:
  # MACK_ROOT/views/some_other/_old_news.html.erb
  # Partials do NOT get wrapped in layouts.
  def latest_news
    render(:partial => "some_other/old_news")
  end

  # This will render a url. If the url does not return a status code of '200',
  # an empty string will be returned by default. The default method for rendering
  # urls is a get.
  def yahoo
    render(:url => "http://www.yahoo.com")
  end

  # This will render a url. If the url does not return a status code of '200',
  # a Mack::Errors::UnsuccessfulRenderUrl exception will be raised.
  def idontexist
    render(:url => "http://www.idontexist.com", :raise_exception => true)
  end

  # This will render a url with a post.
  def post_to_somewhere
    render(:url => "http://www.mackframework.com/post_to_me", :method => :post, 
           :parameters => {:id => 1, :user => "markbates"})
  end

  # This will render a 'local' url. If a domain is not present render url will
  # reach out for the config parameter "mack::site_domain" and prepend that
  # to the url. This can be overridden locally with the :domain option.
  def get_index
    render(:url => "/")
  end
end


179
180
181
182
183
184
185
186
# File 'lib/sea_level/controller_base.rb', line 179

def render(options = {:action => self.action_name})
  raise Mack::Errors::DoubleRender.new if render_performed?
  unless options[:action] || options[:text]
    options = {:layout => false}.merge(options)
  end
  @render_options = options
  @render_performed = true
end

#render_performed?Boolean

Returns true/false depending on whether the render action has been called yet.

Returns:

  • (Boolean)


233
234
235
# File 'lib/sea_level/controller_base.rb', line 233

def render_performed?
  @render_performed
end

#runObject

This does the heavy lifting for controllers. It calls the action, and then completes the rendering of the action to a String to send back to Rack.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/sea_level/controller_base.rb', line 49

def run
  run_filters(:before)
  # check to see if this controller responds to this action.
  # only run public methods!
  if self.public_methods.include?(self.action_name)
    # call the action and capture the results to a variable.
    @result_of_action_called = self.send(self.action_name)
  else
    # there is no action on this controller, so call the render method
    # which will check the view directory and run action.html.erb if it exists.
    render(:action => self.action_name)
  end
  run_filters(:after)
  # do the work of rendering.
  @final_rendered_action = complete_layout_render(complete_action_render)
  run_filters(:after_render)
  @final_rendered_action
end

#sessionObject

Gives access to the session. See Mack::Session for more information.



43
44
45
# File 'lib/sea_level/controller_base.rb', line 43

def session
  self.request.session
end

#wants(header_type, &block) ⇒ Object

In an action wants will run blocks of code based on the content type that has been requested.

Examples:

class MyAwesomeController < Mack::Controller::Base
  def hello
    wants(:html) do
      render(:text => "<html>Hello World</html>")
    end
    wants(:xml) do
      render(:text => "<xml><greeting>Hello World</greeting></xml>")
    end
  end
end

If you were to go to: /my_awesome/hello you would get:

"<html>Hello World</html>"

If you were to go to: /my_awesome/hello.html you would get:

"<html>Hello World</html>"

If you were to go to: /my_awesome/hello.xml you would get:

"<xml><greeting>Hello World</greeting></xml>"


225
226
227
228
229
230
# File 'lib/sea_level/controller_base.rb', line 225

def wants(header_type, &block)
  header_type = header_type.to_sym
  if header_type == params(:format).to_sym
    yield
  end
end