Module: Camping::Controllers

Included in:
Views
Defined in:
lib/camping-unabridged.rb,
lib/camping.rb

Overview

Controllers receive the requests and sends a response back to the client. A controller is simply a class which must implement the HTTP methods it wants to accept:

module Nuts::Controllers
  class Index
    def get
      "Hello World"
    end
  end

  class Posts
    def post
      Post.create(@input) 
      redirect Index
    end
  end  
end

Defining a controller

There are two ways to define controllers: Just defining a class and let Camping figure out the route, or add the route explicitly using R.

If you don’t use R, Camping will first split the controller name up by words (HelloWorld => Hello and World). Then it would do the following:

  • Replace Index with /

  • Replace X with ([^/]+)

  • Replace N with (\d+)

  • Everything else turns into lowercase

  • Join the words with slashes

– NB! N will actually be replaced with (d+), but it needs to be escaped here in order to work correctly with RDoc. ++

Here’s a few examples:

Index   # => /
PostN   # => /post/(\d+)
PageX   # => /page/([^/]+)
Pages   # => /pages

The request

You have these variables which describes the request:

  • @env contains the environment as defined in rack.rubyforge.org/doc/SPEC.html

  • @request is Rack::Request.new(@env)

  • @root is the path where the app is mounted

  • @cookies is a hash with the cookies sent by the client

  • @state is a hash with the sessions (see Camping::Session)

  • @method is the HTTP method in lowercase

The response

You can change these variables to your needs:

  • @status is the HTTP status (defaults to 200)

  • @headers is a hash with the headers

  • @body is the body (a string or something which responds to #each)

  • Any changes in @cookies and @state will also be sent to the client

If you haven’t set @body, it will use the return value of the method:

module Nuts::Controllers
  class Index
    def get
      "This is the body"
    end
  end

  class Posts
    def get
      @body = "Hello World!"
      "This is ignored"
    end
  end
end

Constant Summary collapse

N =
H.new { |_,x| x.downcase }.merge! "N" => '(\d+)', "X" => '([^/]+)', "Index" => ''
I =

Internal controller with no route. Used to show internal messages.

R()

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.D(p, m, e) ⇒ Object

Dispatch routes to controller classes. For each class, routes are checked for a match based on their order in the routing list given to Controllers::R. If no routes were given, the dispatcher uses a slash followed by the name of the controller lowercased.

Controllers are searched in this order:

  • Classes without routes, since they refer to a very specific URL.

  • Classes with routes are searched in order of their creation.

So, define your catch-all controllers last.



567
568
569
570
# File 'lib/camping-unabridged.rb', line 567

def D p,m,e;p='/'if
!p||!p[0];(a=O[:_t].find{|n,_|n==p}) and return [I,:serve,*a]
@r.map{|k|k.urls.map{|x|return(k.method_defined? m)?[k,m,*$~[1..-1].map{|x|U.unescape x}]:
[I, 'r501',m]if p=~/^#{x}\/?$/}};[I,'r404',p] end

.MObject

The route maker, this is called by Camping internally, you shouldn’t need to call it.

Still, it’s worth know what this method does. Since Ruby doesn’t keep track of class creation order, we’re keeping an internal list of the controllers which inherit from R(). This method goes through and adds all the remaining routes to the beginning of the list and ensures all the controllers have the right mixins.

Anyway, if you are calling the URI dispatcher from outside of a Camping server, you’ll definitely need to call this to set things up. Don’t call it too early though. Any controllers added after this method is called won’t work properly



593
594
595
596
# File 'lib/camping-unabridged.rb', line 593

def M;def M;end;constants.
map{|c|k=const_get(c);k.send:include,C,X,Base,Helpers,Models
@r=[k]+@r if @r-[k]==@r;k.meta_def(:urls){["/#{c.to_s.scan(/.[^A-Z]*/).map(&
N.method(:[]))*'/'}"]}if !k.respond_to?:urls}end

.R(*u) ⇒ Object

Add routes to a controller class by piling them into the R method.

The route is a regexp which will match the request path. Anything enclosed in parenthesis will be sent to the method as arguments.

module Camping::Controllers
  class Edit < R '/edit/(\d+)', '/new'
    def get(id)
      if id   # edit
      else    # new
      end
    end
  end
end


548
549
# File 'lib/camping-unabridged.rb', line 548

def R *u;r=@r;Class.
new{meta_def(:urls){u};meta_def(:inherited){|x|r<<x}}end

Instance Method Details

#MObject

:nodoc:



594
# File 'lib/camping-unabridged.rb', line 594

def M;end