diff --git a/README b/README
index 5413823..ed8f459 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ A skeletal Camping blog could look like this:
end
module Blog::Controllers
- class Index < R '/'
+ class Index
def get
@posts = Post.find :all
render :index
@@ -35,7 +35,9 @@ A skeletal Camping blog could look like this:
module Blog::Views
def layout
html do
+ head { title "My Blog" }
body do
+ h1 "My Blog"
self << yield
end
end
diff --git a/lib/camping-unabridged.rb b/lib/camping-unabridged.rb
index 57bf709..d8cd07d 100644
--- a/lib/camping-unabridged.rb
+++ b/lib/camping-unabridged.rb
@@ -17,63 +17,182 @@ def meta_def(m,&b) #:nodoc:
end
end
-# == Camping
-# TODO: Tutorial: Camping.goes, MVC (link to Controllers, Models, Views where
-# they're described in detail), Camping Server (for development), Rack
-# (for production). the create-method. Service overload too, perhaps?
-# Overriding r404, r500 and r501.
+# TODO: Rack (for production). Overriding r404, r500 and r501.
#
-# The camping module contains three modules for separating your application:
+# Ready for developing with Camping? Just follow along and we'll explain
+# everything in a few minutes. If there's a specific thing you're wondering
+# about, here are some guidelines of how Camping and the documentation is organized:
#
-# * Camping::Models for your database interaction classes, all derived from ActiveRecord::Base.
-# * Camping::Controllers for storing controller classes, which map URLs to code.
-# * Camping::Views for storing methods which generate HTML.
+# * All the modules are documentated with a little overview, followed by
+# all the methods defined there.
+# * Camping::Controllers explains all you need to know about taking care
+# of the request and returning a response.
+# * Camping::Models explains how you interact with the database, or other data sources.
+# * Camping::Views explains how you can easily generate HTML from plain Ruby.
+# * Camping::Helpers is a module with useful helpers, both for the controllers and the views.
+# * Camping::Base is a module which is included in all your controllers.
#
-# Of use to you is also one module for storing helpful additional methods:
#
-# * Camping::Helpers which can be used in controllers and views.
+# == Starting My First App
+#
+# When you're going to start a new app in Camping, you simply open
+# your favorite text editor and start writing:
#
-# == The Camping Server
-# TODO: Only for development.
+# require 'camping'
+# Camping.goes :Blog
+#
+# module Blog
+# # lots of code
+# end
+#
+# What's important to know, is that Camping.goes :Blog copies the
+# Camping-module into the Blog-module. So whenever you see Camping in this
+# documentation, you can replace it with Blog and everything should work
+# as expected.
#
-# How do you run Camping apps? Oh, uh... The Camping Server!
+# By not modifying the Camping-module itself, you can have all your apps
+# running in the same process and have less moving parts. In fact, we recommend
+# splitting larger apps into several, smaller ones to make it more manageable.
#
-# The Camping Server is, firstly and thusly, a set of rules. At the very least, The Camping Server must:
+# == The Camping Server (for development)
#
-# * Load all Camping apps in a directory.
-# * Load new apps that appear in that directory.
-# * Mount those apps according to their filename. (e.g. blog.rb is mounted at /blog.)
+# Camping includes a pretty nifty server which is built for development.
+# It follows these rules:
+#
+# * Load all Camping apps in a directory or a file.
+# * Load new apps that appear in that directory or that file.
+# * Mount those apps according to their name. (e.g. Blog is mounted at /blog.)
# * Run each app's create method upon startup.
# * Reload the app if its modification time changes.
# * Reload the app if it requires any files under the same directory and one of their modification times changes.
-# * Support the X-Sendfile header.
+# * Support the X-Sendfile header.
#
-# In fact, Camping comes with its own little The Camping Server.
+# Run it like this:
#
-# At a command prompt, run: camping examples/ and the entire examples/ directory will be served.
+# camping examples/ # Mounts all apps in that directory
+# camping blog.rb # Mounts Blog at /
#
-# Configurations also exist for Apache and Lighttpd. See http://code.whytheluckystiff.net/camping/wiki/TheCampingServer.
+# And visit http://localhost:3301/ in your browser. Ready for some development?
#
-# == The create method
#
-# Many postambles will check for your application's create method and will run it
-# when the web server starts up. This is a good place to check for database tables and create
-# those tables to save users of your application from needing to manually set them up.
+# == MVC
#
-# def Blog.create
-# unless Blog::Models::Post.table_exists?
-# ActiveRecord::Schema.define do
-# create_table :blog_posts, :force => true do |t|
-# t.column :user_id, :integer, :null => false
-# t.column :title, :string, :limit => 255
-# t.column :body, :text
+# Camping follows the MVC-pattern, which means you'll separate your app into
+# three parts: Models, views and controllers. Let's start with the last:
+#
+# === Controllers
+#
+# module Blog::Controllers
+# class Index
+# def get
+# @posts = Post.all
+# render :index
+# end
+# end
+# end
+#
+# The controllers are the heart of your app: They respond to a request from
+# the user, process it and return an appropriate response. Have a look at
+# Camping::Controllers in order to fully understand how controllers work
+# and how you should use them in Camping.
+#
+# === Models
+#
+# module Blog::Models
+# class Post < Base; belongs_to :user; end
+# class Comment < Base; belongs_to :user; end
+# class User < Base; end
+# end
+#
+# Most apps needs to handle _data_ in some way: A blog needs a place to save
+# and retrieve posts and comments; a wiki needs to store the pages somewhere.
+# A _database_ is (most of the time) a great place to save such data. Camping
+# uses (just like Rails) ActiveRecord to abstract the boring details down to
+# beautiful Ruby. Read Camping::Models to learn how to use them in your app.
+#
+# === Views
+#
+# module Blog::Views
+# def layout
+# html do
+# head { title "My Blog" }
+# body do
+# h1 "My Blog"
+# self << yield
# end
# end
# end
+#
+# def index
+# @posts.each do |post|
+# h2 post.title
+# self << post.content
+# end
+# end
+# end
+#
+# Since we're on the web, we need to return the language which the web speaks:
+# HTML. Writing HTML manually can be tedious and boring. Camping uses Markaby
+# which lets you write HTML in Ruby - simple and elegant. As always, read
+# Camping::Views to get a overview of how to use views.
+#
+# === Helpers
+#
+# I know, I know: Helpers don't fit into the MVC-pattern. That doesn't mean
+# they're useless, though. Whenever you need a snippet in several controllers
+# or views, you should refactor it out to a helper. Camping includes a
+# sensible collection of helpers in Camping::Helpers.
+#
+#
+# == Tips & Tricks
+#
+# === The create method
+#
+# It's a rule in Camping which says that the create method should be
+# called when the server starts up. The Camping Server does this, and so
+# should you in your environment.
+#
+# This is a good place to check for database tables and create those tables
+# to save users of your application from needing to manually set them up.
+#
+# def Blog.create
+# Blog::Models::Base.establish_connection(
+# :adapter => 'sqlite3',
+# :database => 'blog.db'
+# )
+# Blog::Models.create_schama
# end
#
-# TODO: Wiki is down.
-# For more tips, see http://code.whytheluckystiff.net/camping/wiki/GiveUsTheCreateMethod.
+# === Service Override
+#
+# Occassionally, you may want to intercept controller calls or do some cleanup
+# afterwards. Many other frameworks have before-, after- and around-filters
+# to do that. Camping has no facility for doing this. It's not worth the bytes.
+#
+# Instead, you can override service, which handles all controller calls.
+# You can do include into specific controllers or right into the main application module.
+#
+# module MySession
+# def service(*a)
+# # Do stuff before
+# @session = MyApp::Session.new
+# # Run regular controller
+# super(*a)
+# ensure
+# # Do stuff after
+# @session.close
+# end
+# end
+#
+# module MyApp
+# include MySession
+#
+# module Controllers
+# class Index
+# include OtherOverload
+# end
+# end
+# end
module Camping
C = self
S = IO.read(__FILE__) rescue nil
@@ -198,14 +317,15 @@ def R(c,*g)
h.any?? u+"?"+U.build_query(h[0]) : u
end
- # Simply builds a complete path from a path +p+ within the app. If your application is
- # mounted at /blog:
+ # Simply builds a complete path from a path +p+ within the app. If your
+ # application is mounted at /blog:
#
# self / "/view/1" #=> "/blog/view/1"
# self / "styles.css" #=> "styles.css"
# self / R(Edit, 1) #=> "/blog/edit/1"
#
def /(p); p[0]==?/?@root+p:p end
+
# Builds a URL route to a controller or a path, returning a URI object.
# This way you'll get the hostname and the port number, a complete URL.
#
@@ -273,7 +393,7 @@ module Base
attr_accessor :input, :cookies, :headers, :body, :status, :root
M = proc { |_, o, n| o.merge(n, &M) }
- # Display a view, calling it by its method name +m+. If a layout
+ # Display a view, calling it by its method name +v+. If a layout
# method is found in Camping::Views, it will be used to wrap the HTML.
#
# module Camping::Controllers
@@ -285,7 +405,7 @@ module Base
# end
# end
#
- # You can also return directly html by just passing a block
+ # You can also return directly HTML by just passing a block
#
def render(v,*a,&b)
mab(/^_/!~v.to_s){send(v,*a,&b)}
@@ -321,7 +441,7 @@ def mab(l=nil,&b)
# You can also switch the body and the header in order to support Rack:
#
# r(302, {'Location' => self / "/view/12"}, '')
- # r(another_app.call(@env))
+ # r(*another_app.call(@env))
#
# See also: #r404, #r500 and #r501
def r(s, b, h = {})
@@ -343,6 +463,8 @@ def r(s, b, h = {})
# NOTE: This method doesn't magically exit your methods and redirect.
# You'll need to return redirect(...) if this isn't the last statement
# in your code.
+ #
+ # See: Controllers
def redirect(*a)
r(302,'','Location'=>URL(*a).to_s)
end
@@ -350,35 +472,26 @@ def redirect(*a)
# Called when a controller was not found. It is mainly used internally, but it can
# also be useful for you, if you want to filter some parameters.
#
- # module Camping
- # def r404(p=env.PATH)
- # @status = 404
- # div do
- # h1 'Camping Problem!'
- # h2 "#{p} not found"
- # end
- # end
- # end
- #
- # See: I
+ # See: Controllers
def r404(p)
P % "#{p} not found"
end
- # If there is a parse error in Camping or in your application's source code, it will not be caught
- # by Camping. The controller class +k+ and request method +m+ (GET, POST, etc.) where the error
+ # If there is a parse error in Camping or in your application's source code,
+ # it will not be caught
+ by Camping. The controller class +k+ and request method +m+ (GET, POST, etc.) where the error
# took place are passed in, along with the Exception +e+ which can be mined for useful info.
#
# You can overide it, but if you have an error in here, it will be uncaught !
#
- # See: I
+ # See: Controllers
def r500(k,m,e)
raise e
end
- # Called if an undefined method is called on a Controller, along with the request method +m+ (GET, POST, etc.)
+ # Called if an undefined method is called on a controller, along with the request method +m+ (GET, POST, etc.)
#
- # See: I
+ # See: Controllers
def r501(m)
P % "#{m.upcase} not implemented"
end
@@ -416,12 +529,10 @@ def initialize(env, m) #:nodoc:
end
end
- # TODO: The wiki is down. Service overload should probably go in Camping.
- # All requests pass through this method before going to the controller. Some magic
- # in Camping can be performed by overriding this method.
+ # All requests pass through this method before going to the controller.
+ # Some magic in Camping can be performed by overriding this method.
#
- # See http://code.whytheluckystiff.net/camping/wiki/BeforeAndAfterOverrides for more
- # on before and after overrides with Camping.
+ # See: Camping
def service(*a)
r = catch(:halt){send(@method, *a)}
@body ||= r