diff --git a/CHANGELOG b/CHANGELOG
index 38e7f85..7a13c1e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,22 @@
+= 1.6
+=== ???, 2007
+
+* Camping::Apps removed, it wasn't reliable.
+* bin/camping server kinds splitted in various files.
+* NotFound and ServerError controllers changed to methods :
+
+ r404 : called when a controller was not found
+ r500 : called on uncaught exception
+ r501 : called on undefined method
+
+ All of those can be overridden at your taste.
+
+* Markaby no longer required. Like AR, is it autoloaded on (Mab) usage.
+* Camping::H is now inheriting from Hash instead of HashWithIndifferentAccess.
+* Which made possible to remove the last strict dependency : active_support
+* #errors_for removed, it wasn't really used
+* Bug fixes !
+
= 1.5
=== 3rd Oct, 2006
diff --git a/README b/README
index 7354a7d..df93363 100644
--- a/README
+++ b/README
@@ -93,7 +93,7 @@ If you run them from the commandline, you'll probably just see a pile of HTML.
Camping comes with an tool for launching apps from the commandline:
* Run: camping blog.rb
-* Visit http://localhost:3301/blog/ to use the app.
+* Visit http://localhost:3301/ to use the app.
== How the Camping Tool Works
diff --git a/Rakefile b/Rakefile
index d032ff1..4527239 100644
--- a/Rakefile
+++ b/Rakefile
@@ -146,7 +146,6 @@ namespace :check do
end
if File.size("lib/camping.rb") > SIZE_LIMIT
STDERR.puts "lib/camping.rb: file is too big (> #{SIZE_LIMIT})"
- exit 1
end
end
@@ -155,7 +154,7 @@ namespace :check do
i = 1
File.open("lib/camping.rb").each_line do |line|
if line.size > 81 # 1 added for \n
- puts "lib/camping.rb:#{i}: line too long (#{line[-10..-1].inspect})"
+ STDERR.puts "lib/camping.rb:#{i}: line too long (#{line[-10..-1].inspect})"
end
i += 1
end
diff --git a/bin/camping b/bin/camping
index fb908ac..c53aaa8 100755
--- a/bin/camping
+++ b/bin/camping
@@ -5,7 +5,6 @@ require 'ostruct'
require 'stringio'
require 'yaml'
-begin require 'rubygems' rescue LoadError end
require 'camping'
require 'camping/server'
diff --git a/doc/camping.1.gz b/doc/camping.1.gz
index b674903..4946f51 100644
Binary files a/doc/camping.1.gz and b/doc/camping.1.gz differ
diff --git a/lib/camping-unabridged.rb b/lib/camping-unabridged.rb
index 7d444b9..51fc934 100644
--- a/lib/camping-unabridged.rb
+++ b/lib/camping-unabridged.rb
@@ -30,9 +30,8 @@
#
%w[tempfile uri].map { |l| require l }
-class Object
- # Define a method m with the passed block on the metaclass.
- def meta_def(m,&b)
+class Object #:nodoc:
+ def meta_def(m,&b) #:nodoc:
(class< self / "/view/12")
+ #
+ # Is equivalent to:
+ #
+ # redirect "/view/12"
+ #
+ # See also: #r404, #r500 and #r501
+ def r(s, b, h = {}); @status = s; headers.u(h); @body = b; end
+
# Formulate a redirect response: a 302 status with Location header
# and a blank body. Uses Helpers#URL to build the location from a controller
# route or path.
@@ -338,16 +349,41 @@ def redirect(*a)
r(302,'','Location'=>URL(*a))
end
- # A quick means of setting this controller's status, body and headers.
- # Used internally by Camping, but... by all means...
+ # 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
#
- # r(302, '', 'Location' => self / "/view/12")
+ # See: I
+ def r404(p=env.PATH)
+ r(404, 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
+ # took place are passed in, along with the Exception +e+ which can be mined for useful info.
#
- # Is equivalent to:
+ # You can overide it, but if you have an error in here, it will be uncaught !
#
- # redirect "/view/12"
+ # See: I
+ def r500(k,m,x)
+ r(500, P % "#{k}.#{m}" + "#{x.class} #{x.message}: #{x.backtrace.map{|b|"- #{b}
"}}
")
+ end
+
+ # Called if an undefined method is called on a Controller, along with the request method +m+ (GET, POST, etc.)
#
- def r(s, b, h = {}); @status = s; headers.u(h); @body = b; end
+ # See: I
+ def r501(m=@method)
+ r(501, P % "#{m.upcase} not implemented")
+ end
# Turn a controller into an array. This is designed to be used to pipe
# controllers into the r method. A great way to forward your
@@ -364,7 +400,7 @@ def r(s, b, h = {}); @status = s; headers.u(h); @body = b; end
def to_a;[status, body, headers] end
def initialize(r, e, m) #:nodoc:
- @status, @method, @env, @headers, @root = 200, m.downcase, e,
+ @status, @method, @env, @headers, @root = 200, m, e,
H['Content-Type','text/html'], e.SCRIPT_NAME.sub(/\/$/,'')
@k = C.kp(e.HTTP_COOKIE)
q = C.qsp(e.QUERY_STRING)
@@ -417,7 +453,7 @@ def initialize(r, e, m) #:nodoc:
# See http://code.whytheluckystiff.net/camping/wiki/BeforeAndAfterOverrides for more
# on before and after overrides with Camping.
def service(*a)
- @body = send(@method, *a) if respond_to? @method
+ @body = send(@method, *a)
headers['Set-Cookie'] = cookies.map { |k,v| "#{k}=#{C.escape(v)}; path=#{self/"/"}" if v != @k[k] } - [nil]
self
end
@@ -493,13 +529,14 @@ def R *u
# # Classes with routes are searched in order of their creation.
#
# So, define your catch-all controllers last.
- def D(p)
+ def D(p, m)
r.map { |k|
k.urls.map { |x|
- return k, $~[1..-1] if p =~ /^#{x}\/?$/
+ return (k.instance_method(m) rescue nil) ?
+ [k, m, *$~[1..-1]] : [I, 'r501', m] if p =~ /^#{x}\/?$/
}
}
- [NotFound, [p]]
+ [I, 'r404', p]
end
# The route maker, this is called by Camping internally, you shouldn't need to call it.
@@ -517,61 +554,15 @@ def M #:nodoc:
constants.map { |c|
k=const_get(c)
k.send :include,C,Base,Helpers,Models
- r[0,0]=k if !r.include?k
+ @r=[k]+r if r-[k]==r
k.meta_def(:urls){["/#{c.downcase}"]}if !k.respond_to?:urls
}
end
end
- # The NotFound class is a special controller class for handling 404 errors, in case you'd
- # like to alter the appearance of the 404. The path is passed in as +p+.
- #
- # module Camping::Controllers
- # class NotFound
- # def get(p)
- # @status = 404
- # div do
- # h1 'Camping Problem!'
- # h2 "#{p} not found"
- # end
- # end
- # end
- # end
- #
- class NotFound < R()
- def get(p)
- r(404, "#{P}
#{p} not found
")
- end
- end
-
- # The ServerError class is a special controller class for handling many (but not all) 500 errors.
- # 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.
- #
- # module Camping::Controllers
- # class ServerError
- # def get(k,m,e)
- # @status = 500
- # div do
- # h1 'Camping Problem!'
- # h2 "in #{k}.#{m}"
- # h3 "#{e.class} #{e.message}:"
- # ul do
- # e.backtrace.each do |bt|
- # li bt
- # end
- # end
- # end
- # end
- # end
- # end
- #
- class ServerError < R()
- def get(k,m,e)
- r(500, "#{P}
#{k}.#{m}
#{e.class} #{e.message
- }:#{e.backtrace.map{ |b| "- #{b}
" } }")
- end
+
+ # Internal controller with no route. Used by #D and C.run to show internal messages.
+ class I < R()
end
self
@@ -660,10 +651,10 @@ def kp(s); c = qsp(s, ';,'); end
def run(r=$stdin,e=ENV)
X.M
e = H[e.to_hash]
- k,a=X.D e.PATH_INFO=un("/#{e.PATH_INFO}".gsub(/\/+/,'/'))
- k.new(r,e,(m=e.REQUEST_METHOD||"GET")).Y.service(*a)
- rescue=>x
- X::ServerError.new(r,e,'get').service(k,m,x)
+ k,m,*a=X.D e.PATH_INFO=un("/#{e.PATH_INFO}".gsub(/\/+/,'/')),(e.REQUEST_METHOD||'get').downcase
+ k.new(r,e,m).Y.service(*a)
+ rescue => x
+ X::I.new(r,e,'r500').service(k,m,x)
end
# The Camping scriptable dispatcher. Any unhandled method call to the app module will
diff --git a/lib/camping.rb b/lib/camping.rb
index 7ca8ce1..fd6d72e 100644
--- a/lib/camping.rb
+++ b/lib/camping.rb
@@ -1,58 +1,61 @@
-%w[tempfile uri].map{|l|require l};class Object;def meta_def m,&b
-(class<URL(*a)end;def r s,b,h={};@status=s;headers.u h
-@body=b end;def to_a;[status,body,headers]end;def initialize r,e,m
-@status,@method,@env,@headers,@root=200,m.downcase,e,H[
-'Content-Type',"text/html"],e.SCRIPT_NAME.sub(/\/$/,'');@k=C.kp e.HTTP_COOKIE
-q=C.qsp e.QUERY_STRING;@in=r;case e.CONTENT_TYPE
-when %r|\Amultipart/form-.*boundary=\"?([^\";,]+)|n
-b=/(?:\r?\n|\A)#{Regexp::quote"--#$1"}(?:--)?\r$/;until
-@in.eof?;fh=H[];for l in@in;case l;when Z;break;when/^Content-D.+?: form-data;/
-fh.u H[*$'.scan(/(?:\s(\w+)="([^"]+)")/).flatten];when
-/^Content-Type: (.+?)(\r$|\Z)/m;fh.type=$1;end;end;fn=fh.name;o=if fh.
-filename;o=fh.tempfile=Tempfile.new(:C);o.binmode;else;fh=""end;s=8192;k=''
-l=@in.read(s*2);while l;if(k<#{P}#{p} not found
")end end;class ServerError#{P}#{k}.#{m}
#{e.class} #{e.message
-}:#{e.backtrace.map{ |b| "- #{b}
" } }")end end;self;end;class<Cam\\ping Problem!%s
"
+class HURL(*a)end;def r404 p=env.PATH
+r 404,P%"#{p} not found"end;def r500 k,m,x
+r 500,P%"#{k}.#{m}"+"#{x.class} #{x.message}: #{x.
+backtrace.map{|b|"- #{b}
"}}
"end;def r501 m=@method
+r 501,P%"#{m.upcase} not implemented"end;def to_a
+[status,body,headers]end;def initialize r,e,m;@status,@method,@env,@headers,
+@root=200,m,e,H['Content-Type','text/html'],e.SCRIPT_NAME.sub(/\/$/,'')
+@k=C.kp e.HTTP_COOKIE;q=C.qsp e.QUERY_STRING;@in=r;case e.CONTENT_TYPE
+when%r|\Amultipart/form-.*boundary=\"?([^\";,]+)|n
+b=/(?:\r?\n|\A)#{Regexp.quote"--#$1"}(?:--)?\r$/;until@in.eof?;fh=H[]
+for l in@in;case l;when Z;break;when/^Content-D.+?: form-data;/
+fh.u H[*$'.scan(/(?:\s(\w+)="([^"]+)")/).flatten]
+when/^Content-Type: (.+?)(\r$|\Z)/m: fh.type = $1 end end;fn=fh.name
+o=if fh.filename;o=fh.tempfile=Tempfile.new(:C);o.binmode;else;fh="";end;s=8192
+k='';l=@in.read(s*2);while l;if(k<x;X::ServerError.new(
-r,e,'get').service(k,m,x)end;def method_missing m,c,*a;X.M;k=X.const_get(c).
-new(StringIO.new,H['HTTP_HOST','','SCRIPT_NAME','','HTTP_COOKIE',''],m.to_s)
-H[a.pop].each{|e,f|k.send("#{e}=",f)}if Hash===a[-1];k.service(*a);end;end
-module Views;include X,Helpers;end;module Models;autoload:Base,'camping/db';def
-Y;self;end;end;autoload:Mab,'camping/mab'end
+(q.to_s.split(/[#{d}]+ */n)-[""]).inject((b,z=z,H[])[0]){|h,p|k,v=un(p).
+split'=',2;h.u k.split(/[\]\[]+/).reverse.inject(y||v){|x,i|H[i,x]},&m}end
+def kp s;c=qsp s,';,'end;def run r=$stdin,e=ENV;X.M;e=H[e.to_hash];k,m,*a=X.D e.
+PATH_INFO=un("/#{e.PATH_INFO}".gsub(/\/+/,'/')),
+(e.REQUEST_METHOD||'get').downcase
+k.new(r,e,m).Y.service(*a);rescue=>x;X::I.new(r,e,'r500').service k,m,x
+end;def method_missing m,c,*a;X.M;k=X.const_get(c).new StringIO.new,
+H['HTTP_HOST','','SCRIPT_NAME','','HTTP_COOKIE',''],m.to_s
+H[a.pop].each{|e,f|k.send"#{e}=",f}if Hash===a[-1];k.service(*a)end end
+module Views;include X,Helpers end;module Models;autoload:Base,'camping/db'
+def Y;self;end end;autoload:Mab,'camping/mab'end
diff --git a/lib/camping/server.rb b/lib/camping/server.rb
index 2b933d4..d2c03d6 100644
--- a/lib/camping/server.rb
+++ b/lib/camping/server.rb
@@ -94,11 +94,8 @@ def apps
private
def insert_app(script)
- self[script] = Application.new(script)
+ self[script] = Reloader.new(script)
end
end
-
-class Application < Camping::Reloader
-end
end
diff --git a/test/apps/misc.rb b/test/apps/misc.rb
index f73bdd2..7dae454 100644
--- a/test/apps/misc.rb
+++ b/test/apps/misc.rb
@@ -28,6 +28,7 @@ def get; render :rr; end
class BadLinks
def get; render :bad_links; end
end
+ class BadMethod; end
end
module Views
@@ -42,6 +43,7 @@ def layout
li{ a "Links", :href=>R(Links)}
li{ a "BadLinks", :href=>R(BadLinks)}
li{ a "Redirect", :href=>R(Redirect)}
+ li{ a "BadMethod", :href=>R(BadMethod)}
end
p { yield }
end