camping 1.5 → 1.5.180

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -2,13 +2,14 @@ require 'rake'
2
2
  require 'rake/clean'
3
3
  require 'rake/gempackagetask'
4
4
  require 'rake/rdoctask'
5
+ require 'rake/testtask'
5
6
  require 'fileutils'
6
7
  include FileUtils
7
8
 
8
9
  NAME = "camping"
9
10
  REV = File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil
10
11
  VERS = ENV['VERSION'] || ("1.5" + (REV ? ".#{REV}" : ""))
11
- CLEAN.include ['**/.*.sw?', '*.gem', '.config']
12
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', 'test/test.log']
12
13
  RDOC_OPTS = ['--quiet', '--title', "Camping, the Documentation",
13
14
  "--opname", "index.html",
14
15
  "--line-numbers",
@@ -74,11 +75,32 @@ spec =
74
75
  s.bindir = "bin"
75
76
  end
76
77
 
78
+ omni =
79
+ Gem::Specification.new do |s|
80
+ s.name = "camping-omnibus"
81
+ s.version = VERS
82
+ s.platform = Gem::Platform::RUBY
83
+ s.summary = "the camping meta-package for updating ActiveRecord, Mongrel and SQLite3 bindings"
84
+ s.description = s.summary
85
+ %w[author email homepage].each { |x| s.__send__("#{x}=", spec.__send__(x)) }
86
+
87
+ s.add_dependency('camping', "=#{VERS}")
88
+ s.add_dependency('activerecord')
89
+ s.add_dependency('sqlite3-ruby', '>=1.1.0.1')
90
+ s.add_dependency('mongrel')
91
+ s.add_dependency('acts_as_versioned')
92
+ s.add_dependency('RedCloth')
93
+ end
94
+
77
95
  Rake::GemPackageTask.new(spec) do |p|
78
96
  p.need_tar = true
79
97
  p.gem_spec = spec
80
98
  end
81
99
 
100
+ Rake::GemPackageTask.new(omni) do |p|
101
+ p.gem_spec = omni
102
+ end
103
+
82
104
  task :install do
83
105
  sh %{rake package}
84
106
  sh %{sudo gem install pkg/#{NAME}-#{VERS}}
@@ -87,3 +109,9 @@ end
87
109
  task :uninstall => [:clean] do
88
110
  sh %{sudo gem uninstall #{NAME}}
89
111
  end
112
+
113
+ Rake::TestTask.new(:test) do |t|
114
+ t.test_files = FileList['test/test_*.rb']
115
+ # t.warning = true
116
+ # t.verbose = true
117
+ end
@@ -203,10 +203,10 @@ module Camping
203
203
  # </div>
204
204
  #
205
205
  def R(c,*g)
206
- p=/\(.+?\)/
207
- g.inject(c.urls.find{|x|x.scan(p).size==g.size}.dup){|s,a|
206
+ p,h=/\(.+?\)/,g.grep(Hash)
207
+ (g-=h).inject(c.urls.find{|x|x.scan(p).size==g.size}.dup){|s,a|
208
208
  s.sub p,C.escape((a[a.class.primary_key]rescue a))
209
- }
209
+ }+(h.any?? "?"+h[0].map{|x|x.map{|z|C.escape z}*"="}*"&": "")
210
210
  end
211
211
 
212
212
  # Shows AR validation errors for the object passed.
@@ -337,7 +337,7 @@ module Camping
337
337
  a.shift if a[0]==:render
338
338
  m=Mab.new({},self)
339
339
  s=m.capture{send(*a,&b)}
340
- s=m.layout{s} if /^_/!~a[0].to_s and m.respond_to?:layout
340
+ s=m.capture{send(:layout){s}} if /^_/!~a[0].to_s and m.respond_to?:layout
341
341
  s
342
342
  end
343
343
 
@@ -368,12 +368,26 @@ module Camping
368
368
  #
369
369
  def r(s, b, h = {}); @status = s; @headers.merge!(h); @body = b; end
370
370
 
371
+ # Turn a controller into an array. This is designed to be used to pipe
372
+ # controllers into the <tt>r</tt> method. A great way to forward your
373
+ # requests!
374
+ #
375
+ # class Read < '/(\d+)'
376
+ # def get(id)
377
+ # Post.find(id)
378
+ # rescue
379
+ # r *Blog.get(:NotFound, @env.REQUEST_URI)
380
+ # end
381
+ # end
382
+ #
383
+ def to_a;[@status, @body, @headers] end
384
+
371
385
  def initialize(r, e, m) #:nodoc:
372
386
  e = H[e.to_hash]
373
387
  @status, @method, @env, @headers, @root = 200, m.downcase, e,
374
388
  {'Content-Type'=>'text/html'}, e.SCRIPT_NAME.sub(/\/$/,'')
375
389
  @k = C.kp(e.HTTP_COOKIE)
376
- qs = C.qs_parse(e.QUERY_STRING)
390
+ qs = C.qsp(e.QUERY_STRING)
377
391
  @in = r
378
392
  if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)|n.match(e.CONTENT_TYPE)
379
393
  b = /(?:\r?\n|\A)#{Regexp::quote("--#$1")}(?:--)?\r$/
@@ -404,11 +418,11 @@ module Camping
404
418
  end
405
419
  o<<l
406
420
  end
407
- qs[fn]=fh if fn
421
+ C.qsp(fn,'&;',fh,qs) if fn
408
422
  fh[:tempfile].rewind if fh.is_a?H
409
423
  end
410
424
  elsif @method == "post"
411
- qs.merge!(C.qs_parse(@in.read))
425
+ qs.merge!(C.qsp(@in.read))
412
426
  end
413
427
  @cookies, @input = @k.dup, qs.dup
414
428
  end
@@ -427,7 +441,9 @@ module Camping
427
441
  # Used by the web server to convert the current request to a string. If you need to
428
442
  # alter the way Camping builds HTTP headers, consider overriding this method.
429
443
  def to_s
430
- "Status: #{@status}#{Z+@headers.map{|k,v|[*v].map{|x|"#{k}: #{x}"}}*Z+Z*2+@body}"
444
+ a=[]
445
+ @headers.map{|k,v|[*v].map{|x|a<<"#{k}: #{x}"}}
446
+ "Status: #{@status}#{Z+a*Z+Z*2+@body}"
431
447
  end
432
448
 
433
449
  end
@@ -518,7 +534,7 @@ module Camping
518
534
  end
519
535
  constants.map { |c|
520
536
  k=const_get(c)
521
- k.send:include,C,Base,Models
537
+ k.send :include,C,Base,Models
522
538
  r[0,0]=k if !r.include?k
523
539
  k.meta_def(:urls){["/#{c.downcase}"]}if !k.respond_to?:urls
524
540
  }
@@ -614,28 +630,28 @@ module Camping
614
630
 
615
631
  # Parses a query string into an Camping::H object.
616
632
  #
617
- # input = Camping.qs_parse("name=Philarp+Tremain&hair=sandy+blonde")
633
+ # input = Camping.qsp("name=Philarp+Tremain&hair=sandy+blonde")
618
634
  # input.name
619
635
  # #=> "Philarp Tremaine"
620
636
  #
621
637
  # Also parses out the Hash-like syntax used in PHP and Rails and builds
622
638
  # nested hashes from it.
623
639
  #
624
- # input = Camping.qs_parse("post[id]=1&post[user]=_why")
640
+ # input = Camping.qsp("post[id]=1&post[user]=_why")
625
641
  # #=> {'post' => {'id' => '1', 'user' => '_why'}}
626
642
  #
627
- def qs_parse(qs, d = '&;')
643
+ def qsp(qs, d='&;', y=nil, z=H[])
628
644
  m = proc {|_,o,n|o.u(n,&m)rescue([*o]<<n)}
629
645
  (qs||'').
630
646
  split(/[#{d}] */n).
631
- inject(H[]) { |h,p| k, v=un(p).split('=',2)
647
+ inject((b,z=z,H[])[0]) { |h,p| k, v=un(p).split('=',2)
632
648
  h.u(k.split(/[\]\[]+/).reverse.
633
- inject(v) { |x,i| H[i,x] },&m)
649
+ inject(y||v) { |x,i| H[i,x] },&m)
634
650
  }
635
651
  end
636
652
 
637
653
  # Parses a string of cookies from the <tt>Cookie</tt> header.
638
- def kp(s); c = qs_parse(s, ';,'); end
654
+ def kp(s); c = qsp(s, ';,'); end
639
655
 
640
656
  # Fields a request through Camping. For traditional CGI applications, the method can be
641
657
  # executed without arguments.
@@ -661,7 +677,7 @@ module Camping
661
677
  X.M
662
678
  k,a=X.D un("/#{e['PATH_INFO']}".gsub(/\/+/,'/'))
663
679
  k.new(r,e,(m=e['REQUEST_METHOD']||"GET")).Y.service *a
664
- rescue Exception=>x
680
+ rescue Object=>x
665
681
  X::ServerError.new(r,e,'get').service(k,m,x)
666
682
  end
667
683
 
@@ -718,7 +734,7 @@ module Camping
718
734
  #
719
735
  # Models cannot be referred to in Views at this time.
720
736
  module Models
721
- autoload:Base,'camping/db'
737
+ autoload :Base,'camping/db'
722
738
  def Y;self;end
723
739
  end
724
740
 
data/lib/camping.rb CHANGED
@@ -1,30 +1,33 @@
1
1
  %w[active_support markaby tempfile uri].map{|l|require l}
2
2
  module Camping;Apps=[];C=self;S=IO.read(__FILE__).sub(/S=I.+$/,'')
3
- P="Cam\ping Problem!";module Helpers;def R c,*g;p=/\(.+?\)/;g.inject(c.
4
- urls.find{|x|x.scan(p).size==g.size}.dup){|s,a|s.sub p,C.escape((a[
5
- a.class.primary_key]rescue a))}end;def URL c='/',*a;c=R(c,*a)if c.
3
+ P="Cam\ping Problem!";module Helpers;def R(c,*g);p,h=/\(.+?\)/,g.grep(Hash)
4
+ (g-=h).inject(c.urls.find{|x|x.scan(p).size==g.size}.dup){|s,a|s.sub p,C.
5
+ escape((a[a.class.primary_key]rescue a))}+(h.any?? "?"+h[0].map{|x|x.map{|z|C.
6
+ escape z}*"="}*"&": "")end;def URL c='/',*a;c=R(c,*a)if c.
6
7
  respond_to?:urls;c=self/c;c="//"+@env.HTTP_HOST+c if c[/^\//];URI(c)end;def/p
7
8
  p[/^\//]?@root+p : p end;def errors_for o;ul.errors{o.errors.each_full{|x|li x}
8
9
  }if o.errors.any?end end;module Base;include Helpers;attr_accessor:input,
9
10
  :cookies,:env,:headers,:body,:status,:root;def method_missing*a,&b
10
- a.shift if a[0]==:render;m=Mab.new({},self);s=m.capture{send(*a,&b)};s=m.layout{s}if
11
- /^_/!~a[0].to_s and m.respond_to?:layout;s end;def r s,b,h={};@status=s;@headers.
12
- merge!h;@body=b end;def redirect*a;r 302,'','Location'=>URL(*a)end;Z="\r\n"
11
+ a.shift if a[0]==:render;m=Mab.new({},self);s=m.capture{send(*a,&b)}
12
+ s=m.capture{send(:layout){s}} if /^_/!~a[0].to_s and m.respond_to?:layout
13
+ s end;def r s,b,h={};@status=s;@headers.merge!h;@body=b end
14
+ def redirect*a;r 302,'','Location'=>URL(*a)end;Z="\r\n"
15
+ def to_a;[@status,@body,@headers]end
13
16
  def initialize r,e,m;e=H[e.to_hash];@status,@method,@env,@headers,@root=200,m.
14
17
  downcase,e,{'Content-Type'=>"text/html"},e.SCRIPT_NAME.sub(/\/$/,'')
15
- @k=C.kp e.HTTP_COOKIE;q=C.qs_parse e.QUERY_STRING;@in=r
18
+ @k=C.kp e.HTTP_COOKIE;q=C.qsp e.QUERY_STRING;@in=r
16
19
  if%r|\Amultipart/form-.*boundary=\"?([^\";,]+)|n.match e.CONTENT_TYPE
17
20
  b=/(?:\r?\n|\A)#{Regexp::quote("--#$1")}(?:--)?\r$/;until@in.eof?;fh=H[];for l in@in
18
21
  case l;when Z;break;when/^Content-D.+?: form-data;/;fh.u H[*$'.
19
22
  scan(/(?:\s(\w+)="([^"]+)")/).flatten];when/^Content-Type: (.+?)(\r$|\Z)/m;fh[
20
23
  :type]=$1;end;end;fn=fh[:name];o=if fh[:filename];o=fh[:tempfile]=Tempfile.new(:C)
21
24
  o.binmode;else;fh=""end;while l=@in.read(16384);if l=~b;o<<$`.chomp;@in.seek(-$'.
22
- size,IO::SEEK_CUR);break;end;o<<l;end;q[fn]=fh if fn;fh[:tempfile].rewind if
23
- fh.is_a?H;end;elsif@method=="post";q.u C.qs_parse(@in.read)end;@cookies,@input=
25
+ size,IO::SEEK_CUR);break;end;o<<l;end;C.qsp(fn,'&;',fh,q) if fn;fh[:tempfile].rewind if
26
+ fh.is_a?H;end;elsif@method=="post";q.u C.qsp(@in.read)end;@cookies,@input=
24
27
  @k.dup,q.dup end;def service*a;@body=send(@method,*a)if respond_to?@method
25
28
  @headers["Set-Cookie"]=@cookies.map{|k,v|"#{k}=#{C.escape(v)}; path=#{self/'/'
26
- }"if v!=@k[k]}-[nil];self end;def to_s;"Status: #{@status}#{Z+@headers.map{|k,v|
27
- [*v].map{|x|"#{k}: #{x}"}}*Z+Z*2+@body}"end;end
29
+ }"if v!=@k[k]}-[nil];self end;def to_s;a=[];@headers.map{|k,v|[*v].map{|x|a<<
30
+ "#{k}: #{x}"}};"Status: #{@status}#{Z+a*Z+Z*2+@body}"end;end
28
31
  X=module Controllers;@r=[];class<<self;def r;@r;end;def R*u;r=@r;Class.new{
29
32
  meta_def(:urls){u};meta_def(:inherited){|x|r<<x}}end;def M;def M;end;constants.map{|c|
30
33
  k=const_get(c);k.send:include,C,Base,Models;r[0,0]=k if !r.include?k;k.meta_def(
@@ -36,12 +39,12 @@ ServerError<R();def get k,m,e;r(500,Mab.new{h1 P;h2"#{k}.#{m}";h3"#{e.class
36
39
  self;def goes m;eval S.gsub(/Camping/,m.to_s).gsub("A\pps=[]","Cam\ping::Apps<<\
37
40
  self"),TOPLEVEL_BINDING;end;def escape s;s.to_s.gsub(/[^ \w.-]+/n){'%'+($&.
38
41
  unpack('H2'*$&.size)*'%').upcase}.tr(' ','+')end;def un s;s.tr('+',' ').gsub(
39
- /%([\da-f]{2})/in){[$1].pack('H*')}end;def qs_parse q,d='&;';m=proc{|_,o,n|o.u(
40
- n,&m)rescue([*o]<<n)};q.to_s.split(/[#{d}] */n).inject(H[]){|h,p|k,v=un(p).
41
- split('=',2);h.u k.split(/[\]\[]+/).reverse.inject(v){|x,i|H[i,x]},&m}end;def
42
- kp s;c=qs_parse(s,';,')end;def run r=$stdin,e=ENV;X.M;k,a=X.D un("/#{e[
42
+ /%([\da-f]{2})/in){[$1].pack('H*')}end;def qsp q,d='&;',y=nil,z=H[];m=proc{|_,o,n|o.u(
43
+ n,&m)rescue([*o]<<n)};q.to_s.split(/[#{d}] */n).inject((b,z=z,H[])[0]){|h,p|k,v=un(p).
44
+ split('=',2);h.u k.split(/[\]\[]+/).reverse.inject(y||v){|x,i|H[i,x]},&m}end;def
45
+ kp s;c=qsp(s,';,')end;def run r=$stdin,e=ENV;X.M;k,a=X.D un("/#{e[
43
46
  'PATH_INFO']}".gsub(/\/+/,'/'));k.new(r,e,(m=e['REQUEST_METHOD']||"GET")).Y.
44
- service *a;rescue Exception=>x;X::ServerError.new(r,e,'get').service(k,m,x)end
47
+ service *a;rescue Object=>x;X::ServerError.new(r,e,'get').service(k,m,x)end
45
48
  def method_missing m,c,*a;X.M;k=X.const_get(c).new(StringIO.new,H['HTTP_HOST',
46
49
  '','SCRIPT_NAME','','HTTP_COOKIE',''],m.to_s);H.new(a.pop).each{|e,f|k.send(
47
50
  "#{e}=",f)}if Hash===a[-1];k.service *a;end;end;module Views;include X,Helpers
@@ -58,6 +58,8 @@ module Camping
58
58
  class FastCGI
59
59
  CHUNK_SIZE=(4 * 1024)
60
60
 
61
+ attr_reader :mounts
62
+
61
63
  # Creates a Camping::FastCGI class with empty mounts.
62
64
  def initialize
63
65
  @mounts = {}
@@ -69,71 +71,12 @@ class FastCGI
69
71
  dir.gsub!(/\/+$/, '')
70
72
  @mounts[dir] = app
71
73
  end
74
+
72
75
  #
73
76
  # Starts the FastCGI main loop.
74
- def start
77
+ def start(&blk)
75
78
  FCGI.each do |req|
76
- dir, app = nil
77
- begin
78
- root, path = "/"
79
- if ENV['FORCE_ROOT'] and ENV['FORCE_ROOT'].to_i == 1
80
- path = req.env['REQUEST_URI']
81
- else
82
- root = req.env['SCRIPT_NAME']
83
- path = req.env['PATH_INFO']
84
- end
85
-
86
- dir, app = @mounts.max { |a,b| match(path, a[0]) <=> match(path, b[0]) }
87
- unless dir and app
88
- dir, app = '/', Camping
89
- end
90
- yield dir, app if block_given?
91
-
92
- req.env['SERVER_SCRIPT_NAME'] = req.env['SCRIPT_NAME']
93
- req.env['SERVER_PATH_INFO'] = req.env['PATH_INFO']
94
- req.env['SCRIPT_NAME'] = File.join(root, dir)
95
- req.env['PATH_INFO'] = path.gsub(/^#{dir}/, '')
96
-
97
- controller = app.run(req.in, req.env)
98
- sendfile = nil
99
- headers = {}
100
- controller.headers.each do |k, v|
101
- if k =~ /^X-SENDFILE$/i and !ENV['SERVER_X_SENDFILE']
102
- sendfile = v
103
- else
104
- headers[k] = v
105
- end
106
- end
107
-
108
- body = controller.body
109
- controller.body = ""
110
- controller.headers = headers
111
-
112
- req.out << controller.to_s
113
- if sendfile
114
- File.open(sendfile, "rb") do |f|
115
- while chunk = f.read(CHUNK_SIZE) and chunk.length > 0
116
- req.out << chunk
117
- end
118
- end
119
- elsif body.respond_to? :read
120
- while chunk = body.read(CHUNK_SIZE) and chunk.length > 0
121
- req.out << chunk
122
- end
123
- body.close if body.respond_to? :close
124
- else
125
- req.out << body.to_s
126
- end
127
- rescue Exception => e
128
- req.out << "Content-Type: text/html\r\n\r\n" +
129
- "<h1>Camping Problem!</h1>" +
130
- "<h2><strong>#{root}</strong>#{path}</h2>" +
131
- "<h3>#{e.class} #{esc e.message}</h3>" +
132
- "<ul>" + e.backtrace.map { |bt| "<li>#{esc bt}</li>" }.join + "</ul>" +
133
- "<hr /><p>#{req.env.inspect}</p>"
134
- ensure
135
- req.finish
136
- end
79
+ camp_do(req, &blk)
137
80
  end
138
81
  end
139
82
 
@@ -173,7 +116,7 @@ class FastCGI
173
116
  fast.start do |dir, app|
174
117
  Dir[File.join(path, dir, '*.rb')].each do |script|
175
118
  smount = "/" + File.basename(script, '.rb')
176
- script_load[script] unless @mounts.has_key? smount
119
+ script_load[script] unless fast.mounts.has_key? smount
177
120
  end
178
121
  end
179
122
  else
@@ -183,6 +126,71 @@ class FastCGI
183
126
 
184
127
  private
185
128
 
129
+ def camp_do(req)
130
+ root, path, dir, app = "/"
131
+ if ENV['FORCE_ROOT'] and ENV['FORCE_ROOT'].to_i == 1
132
+ path = req.env['SCRIPT_NAME']
133
+ else
134
+ root = req.env['SCRIPT_NAME']
135
+ path = req.env['PATH_INFO']
136
+ end
137
+
138
+ dir, app = @mounts.max { |a,b| match(path, a[0]) <=> match(path, b[0]) }
139
+ unless dir and app
140
+ dir, app = '/', Camping
141
+ end
142
+ yield dir, app if block_given?
143
+
144
+ req.env['SERVER_SCRIPT_NAME'] = req.env['SCRIPT_NAME']
145
+ req.env['SERVER_PATH_INFO'] = req.env['PATH_INFO']
146
+ req.env['SCRIPT_NAME'] = File.join(root, dir)
147
+ req.env['PATH_INFO'] = path.gsub(/^#{dir}/, '')
148
+
149
+ controller = app.run(SeekStream.new(req.in), req.env)
150
+ sendfile = nil
151
+ headers = {}
152
+ controller.headers.each do |k, v|
153
+ if k =~ /^X-SENDFILE$/i and !ENV['SERVER_X_SENDFILE']
154
+ sendfile = v
155
+ else
156
+ headers[k] = v
157
+ end
158
+ end
159
+
160
+ body = controller.body
161
+ controller.body = ""
162
+ controller.headers = headers
163
+
164
+ req.out << controller.to_s
165
+ if sendfile
166
+ File.open(sendfile, "rb") do |f|
167
+ while chunk = f.read(CHUNK_SIZE) and chunk.length > 0
168
+ req.out << chunk
169
+ end
170
+ end
171
+ elsif body.respond_to? :read
172
+ while chunk = body.read(CHUNK_SIZE) and chunk.length > 0
173
+ req.out << chunk
174
+ end
175
+ body.close if body.respond_to? :close
176
+ else
177
+ req.out << body.to_s
178
+ end
179
+ rescue Exception => e
180
+ req.out << server_error(root, path, exc, req)
181
+ ensure
182
+ req.finish
183
+ end
184
+
185
+ def server_error(root, path, exc, req)
186
+ "Content-Type: text/html\r\n\r\n" +
187
+ "<h1>Camping Problem!</h1>" +
188
+ "<h2><strong>#{root}</strong>#{path}</h2>" +
189
+ "<h3>#{exc.class} #{esc exc.message}</h3>" +
190
+ "<ul>" + exc.backtrace.map { |bt| "<li>#{esc bt}</li>" }.join + "</ul>" +
191
+ "<hr /><p>#{req.env.inspect}</p>"
192
+ end
193
+
186
194
  def match(path, mount)
187
195
  m = path.match(/^#{Regexp::quote mount}(\/|$)/)
188
196
  if m; m.end(0)
@@ -194,5 +202,43 @@ class FastCGI
194
202
  str.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
195
203
  end
196
204
 
205
+ class SeekStream
206
+ def initialize(stream)
207
+ @last_read = ""
208
+ @stream = stream
209
+ @buffer = ""
210
+ end
211
+ def eof?
212
+ @buffer.empty? && @stream.eof?
213
+ end
214
+ def each
215
+ while true
216
+ pull(1024) until eof? or @buffer.index("\n")
217
+ return nil if eof?
218
+ yield @buffer.slice!(0..(@buffer.index("\n") || -1))
219
+ end
220
+ end
221
+ def pull(len)
222
+ @buffer += @stream.read(len).to_s
223
+ end
224
+ def read(len = 16384)
225
+ pull(len)
226
+ @last_read =
227
+ if eof?
228
+ nil
229
+ else
230
+ @buffer.slice!(0...len)
231
+ end
232
+ end
233
+ def seek(len, typ)
234
+ raise NotImplementedError, "only IO::SEEK_CUR is supported with SeekStream" if typ != IO::SEEK_CUR
235
+ raise NotImplementedError, "only rewinding is supported with SeekStream" if len > 0
236
+ raise NotImplementedError, "rewinding #{-len} past the buffer #{@last_read.size} start not supported with SeekStream" if -len > @last_read.size
237
+ @buffer = @last_read[len..-1] + @buffer
238
+ @last_read = ""
239
+ self
240
+ end
241
+ end
242
+
197
243
  end
198
244
  end
@@ -146,13 +146,7 @@ class Reloader
146
146
  Camping::Models::Base.logger = Logger.new(@log == "-" ? STDOUT : @log)
147
147
  end
148
148
 
149
- begin
150
- Camping::Models::Session.create_schema
151
- rescue MissingSourceFile
152
- puts "** #$0 stopped: SQLite3 not found, please install."
153
- puts "** See http://code.whytheluckystiff.net/camping/wiki/BeAlertWhenOnSqlite3 for instructions."
154
- exit
155
- end
149
+ Camping::Models::Session.create_schema
156
150
 
157
151
  if @database and @database[:adapter] == 'sqlite3'
158
152
  begin
@@ -56,7 +56,7 @@ class CampingHandler < WEBrick::HTTPServlet::DefaultFileHandler
56
56
  end
57
57
 
58
58
  if @local_path
59
- do_GET(req, res)
59
+ do_GET(req, resp)
60
60
  else
61
61
  resp.body = controller.body.to_s
62
62
  end
@@ -0,0 +1,55 @@
1
+ require 'mosquito'
2
+
3
+ Camping.goes :XhtmlTrans
4
+
5
+ module XhtmlTrans
6
+ module Controllers
7
+ class WithLayout < R '/with_layout'
8
+ def get
9
+ render :with_layout
10
+ end
11
+ end
12
+
13
+ class WithoutLayout < R '/without_layout'
14
+ def get
15
+ render :_without_layout
16
+ end
17
+ end
18
+ end
19
+
20
+ module Views
21
+ def layout
22
+ xhtml_transitional do
23
+ head do title "title" end
24
+ body do capture { yield } end
25
+ end
26
+ end
27
+
28
+ def with_layout
29
+ h1 "With layout"
30
+ end
31
+
32
+ def _without_layout
33
+ xhtml_transitional do
34
+ head do title "title" end
35
+ body do h1 "Without layout" end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ class XhtmlTransTest < Camping::FunctionalTest
42
+ def test_with_layout
43
+ get '/with_layout'
44
+
45
+ assert(@response.body =~ /DOCTYPE/, "No doctype defined")
46
+ end
47
+
48
+ def test_without_layout
49
+ get '/without_layout'
50
+
51
+ assert(@response.body =~ /DOCTYPE/, "No doctype defined")
52
+ end
53
+
54
+ end
55
+
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0.1
2
+ rubygems_version: 0.9.0.8
3
3
  specification_version: 1
4
4
  name: camping
5
5
  version: !ruby/object:Gem::Version
6
- version: "1.5"
7
- date: 2006-10-03 00:00:00 -06:00
6
+ version: 1.5.180
7
+ date: 2007-01-06 00:00:00 -07:00
8
8
  summary: minature rails for stay-at-home moms
9
9
  require_paths:
10
10
  - lib
@@ -34,6 +34,7 @@ files:
34
34
  - Rakefile
35
35
  - bin/camping
36
36
  - doc/camping.1.gz
37
+ - test/test_xhtml_trans.rb
37
38
  - lib/camping
38
39
  - lib/camping.rb
39
40
  - lib/camping-unabridged.rb
@@ -45,9 +46,9 @@ files:
45
46
  - extras/permalink.gif
46
47
  - extras/Camping.gif
47
48
  - extras/flipbook_rdoc.rb
49
+ - examples/campsh.rb
48
50
  - examples/tepee.rb
49
51
  - examples/blog.rb
50
- - examples/campsh.rb
51
52
  - CHANGELOG
52
53
  test_files: []
53
54