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}:

") + 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 - }:

#{p} not found

")end end;class ServerError#{P}

#{k}.#{m}

#{e.class} #{e.message -}:
    #{e.backtrace.map{ |b| "
  • #{b}
  • " } }")end end;self;end;class<URL(*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