Module: Mack::Controller

Includes:
Utils::ForgeryDetector
Defined in:
lib/mack/controller/controller.rb,
lib/mack/controller/tell.rb,
lib/mack/controller/filter.rb

Overview

:nodoc:

Defined Under Namespace

Modules: ClassMethods, Tell Classes: Filter, Registry

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils::ForgeryDetector

#detect_forgery

Instance Attribute Details

#action_nameObject (readonly)

The name of the action being requested.



22
23
24
# File 'lib/mack/controller/controller.rb', line 22

def action_name
  @action_name
end

#caught_exceptionObject

If an exception was thrown by a request this represents that error.



26
27
28
# File 'lib/mack/controller/controller.rb', line 26

def caught_exception
  @caught_exception
end

#controller_nameObject (readonly)

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



20
21
22
# File 'lib/mack/controller/controller.rb', line 20

def controller_name
  @controller_name
end

#cookiesObject (readonly)

See Mack::CookieJar for more information.



24
25
26
# File 'lib/mack/controller/controller.rb', line 24

def cookies
  @cookies
end

#requestObject (readonly)

See Mack::Request for more information.



16
17
18
# File 'lib/mack/controller/controller.rb', line 16

def request
  @request
end

#responseObject (readonly)

See Mack::Response for more information.



18
19
20
# File 'lib/mack/controller/controller.rb', line 18

def response
  @response
end

Class Method Details

.included(base) ⇒ Object

Make sure that all the class level methods got included into the receiver’s class



365
366
367
368
369
370
# File 'lib/mack/controller/controller.rb', line 365

def self.included(base)
  Mack::Controller::Registry.add(base)
  base.extend(ClassMethods)
  base.extend(Mack::Utils::ForgeryDetector::ClassMethods)
  base.before_filter :detect_forgery
end

Instance Method Details

#configure_controller(request, response, cookies) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'lib/mack/controller/controller.rb', line 28

def configure_controller(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

#loggerObject

Gives access to the Mack.logger.



136
137
138
# File 'lib/mack/controller/controller.rb', line 136

def logger
  Mack.logger
end

#paramsObject

Gives access to all the parameters for this request.



40
41
42
# File 'lib/mack/controller/controller.rb', line 40

def params
  self.request.params
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.



90
91
92
93
94
95
96
# File 'lib/mack/controller/controller.rb', line 90

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(render_type = :action, render_value = self.action_name, options = {}) ⇒ 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.

You can also specify the response status code as part of the options hash.

Examples:

class MyAwesomeController
  include Mack::Controller

  # 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

  # This will render 'application/404' and set the response status code to 404
  def to_the_unknown
    return render(:action, '/application/404', :status => 404)
  end

end


261
262
263
264
265
266
267
268
269
270
# File 'lib/mack/controller/controller.rb', line 261

def render(render_type = :action, render_value = self.action_name, options = {})
  raise Mack::Errors::DoubleRender.new if render_performed?
  response.status = options[:status] if options[:status]
  options = {:layout => layout}.merge(options)
  response.content_type = options[:content_type] if options[:content_type]
  options.delete(:content_type)
  @view_template = Mack::Rendering::ViewTemplate.new(render_type, render_value, 
  {:format => params[:format].to_sym, :controller => self}.merge(options))
  @render_performed = true
end

#render_performed?Boolean

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

Returns:

  • (Boolean)


131
132
133
# File 'lib/mack/controller/controller.rb', line 131

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.



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
# File 'lib/mack/controller/controller.rb', line 52

def run
  begin
    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.to_s)
      # call the action and capture the results to a variable.
      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 = do_render
    run_filters(:after_render)
    return @final_rendered_action
  rescue Mack::Errors::FilterChainHalted => e
    if render_performed?
      run_filters(:after)
      # do the work of rendering.
      @final_rendered_action = do_render
      run_filters(:after_render)
      return @final_rendered_action
    else
      raise e
    end
  end

end

#sessionObject

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



45
46
47
48
# File 'lib/mack/controller/controller.rb', line 45

def session
  raise Mack::Errors::NoSessionError.new if self.request.session.nil?
  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
  include Mack::Controller

  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>"


123
124
125
126
127
128
# File 'lib/mack/controller/controller.rb', line 123

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