camping 1.5.180 → 2.0.rc0

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.
Files changed (64) hide show
  1. data/CHANGELOG +35 -0
  2. data/README +43 -68
  3. data/Rakefile +155 -86
  4. data/bin/camping +64 -246
  5. data/book/01_introduction +19 -0
  6. data/book/02_getting_started +443 -0
  7. data/book/51_upgrading +93 -0
  8. data/doc/api.html +1953 -0
  9. data/doc/book.html +73 -0
  10. data/doc/book/01_introduction.html +57 -0
  11. data/doc/book/02_getting_started.html +573 -0
  12. data/doc/book/51_upgrading.html +146 -0
  13. data/doc/created.rid +1 -0
  14. data/{extras → doc/images}/Camping.gif +0 -0
  15. data/doc/images/loadingAnimation.gif +0 -0
  16. data/{extras → doc/images}/permalink.gif +0 -0
  17. data/doc/index.html +148 -0
  18. data/doc/js/camping.js +79 -0
  19. data/doc/js/jquery.js +32 -0
  20. data/doc/rdoc.css +117 -0
  21. data/examples/blog.rb +280 -181
  22. data/extras/images/badge.gif +0 -0
  23. data/extras/images/boys-life.png +0 -0
  24. data/extras/images/deerputer.png +0 -0
  25. data/extras/images/diagram.png +0 -0
  26. data/extras/images/hill.png +0 -0
  27. data/extras/images/i-wish.png +0 -0
  28. data/extras/images/latl.png +0 -0
  29. data/extras/images/little-wheels.png +0 -0
  30. data/extras/images/square-badge.png +0 -0
  31. data/extras/images/uniform.png +0 -0
  32. data/extras/images/whale-bounce.png +0 -0
  33. data/extras/rdoc/generator/singledarkfish.rb +205 -0
  34. data/extras/rdoc/generator/template/flipbook/images/Camping.gif +0 -0
  35. data/extras/rdoc/generator/template/flipbook/images/loadingAnimation.gif +0 -0
  36. data/extras/rdoc/generator/template/flipbook/images/permalink.gif +0 -0
  37. data/extras/rdoc/generator/template/flipbook/js/camping.js +79 -0
  38. data/extras/rdoc/generator/template/flipbook/js/jquery.js +32 -0
  39. data/extras/rdoc/generator/template/flipbook/page.rhtml +30 -0
  40. data/extras/rdoc/generator/template/flipbook/rdoc.css +117 -0
  41. data/extras/rdoc/generator/template/flipbook/readme.rhtml +31 -0
  42. data/extras/rdoc/generator/template/flipbook/reference.rhtml +71 -0
  43. data/extras/rdoc/generator/template/flipbook/toc.rhtml +43 -0
  44. data/lib/camping-unabridged.rb +420 -481
  45. data/lib/camping.rb +40 -55
  46. data/lib/camping/{db.rb → ar.rb} +5 -8
  47. data/lib/camping/mab.rb +26 -0
  48. data/lib/camping/reloader.rb +175 -147
  49. data/lib/camping/server.rb +178 -0
  50. data/lib/camping/session.rb +34 -121
  51. data/test/apps/env_debug.rb +65 -0
  52. data/test/apps/forms.rb +95 -0
  53. data/test/apps/forward_to_other_controller.rb +60 -0
  54. data/test/apps/migrations.rb +97 -0
  55. data/test/apps/misc.rb +86 -0
  56. data/test/apps/sessions.rb +38 -0
  57. metadata +120 -80
  58. data/doc/camping.1.gz +0 -0
  59. data/examples/campsh.rb +0 -630
  60. data/examples/tepee.rb +0 -242
  61. data/extras/flipbook_rdoc.rb +0 -491
  62. data/lib/camping/fastcgi.rb +0 -244
  63. data/lib/camping/webrick.rb +0 -65
  64. data/test/test_xhtml_trans.rb +0 -55
@@ -1,244 +0,0 @@
1
- # == About camping/fastcgi.rb
2
- #
3
- # Camping works very well with FastCGI, since your application is only loaded
4
- # once -- when FastCGI starts. In addition, this class lets you mount several
5
- # Camping apps under a single FastCGI process, to help save memory costs.
6
- #
7
- # So where do you use the Camping::FastCGI class? Use it in your application's
8
- # postamble and then you can point your web server directly at your application.
9
- # See Camping::FastCGI docs for more.
10
- require 'camping'
11
- require 'fcgi'
12
-
13
- module Camping
14
- # Camping::FastCGI is a small class for hooking one or more Camping apps up to
15
- # FastCGI. Generally, you'll use this class in your application's postamble.
16
- #
17
- # == The Smallest Example
18
- #
19
- # if __FILE__ == $0
20
- # require 'camping/fastcgi'
21
- # Camping::FastCGI.start(YourApp)
22
- # end
23
- #
24
- # This example is stripped down to the basics. The postamble has no database
25
- # connection. It just loads this class and calls Camping::FastCGI.start.
26
- #
27
- # Now, in Lighttpd or Apache, you can point to your app's file, which will
28
- # be executed, only to discover that your app now speaks the FastCGI protocol.
29
- #
30
- # Here's a sample lighttpd.conf (tested with Lighttpd 1.4.11) to serve as example:
31
- #
32
- # server.port = 3044
33
- # server.bind = "127.0.0.1"
34
- # server.modules = ( "mod_fastcgi" )
35
- # server.document-root = "/var/www/camping/blog/"
36
- # server.errorlog = "/var/www/camping/blog/error.log"
37
- #
38
- # #### fastcgi module
39
- # fastcgi.server = ( "/" => (
40
- # "localhost" => (
41
- # "socket" => "/tmp/camping-blog.socket",
42
- # "bin-path" => "/var/www/camping/blog/blog.rb",
43
- # "check-local" => "disable",
44
- # "max-procs" => 1 ) ) )
45
- #
46
- # The file <tt>/var/www/camping/blog/blog.rb</tt> is the Camping app with
47
- # the postamble.
48
- #
49
- # == Mounting Many Apps
50
- #
51
- # require 'camping/fastcgi'
52
- # fast = Camping::FastCGI.new
53
- # fast.mount("/blog", Blog)
54
- # fast.mount("/tepee", Tepee)
55
- # fast.mount("/", Index)
56
- # fast.start
57
- #
58
- class FastCGI
59
- CHUNK_SIZE=(4 * 1024)
60
-
61
- attr_reader :mounts
62
-
63
- # Creates a Camping::FastCGI class with empty mounts.
64
- def initialize
65
- @mounts = {}
66
- end
67
- # Mounts a Camping application. The +dir+ being the name of the directory
68
- # to serve as the application's root. The +app+ is a Camping class.
69
- def mount(dir, app)
70
- dir.gsub!(/\/{2,}/, '/')
71
- dir.gsub!(/\/+$/, '')
72
- @mounts[dir] = app
73
- end
74
-
75
- #
76
- # Starts the FastCGI main loop.
77
- def start(&blk)
78
- FCGI.each do |req|
79
- camp_do(req, &blk)
80
- end
81
- end
82
-
83
- # A simple single-app starter mechanism
84
- #
85
- # Camping::FastCGI.start(Blog)
86
- #
87
- def self.start(app)
88
- cf = Camping::FastCGI.new
89
- cf.mount("/", app)
90
- cf.start
91
- end
92
-
93
- # Serve an entire directory of Camping apps. (See
94
- # http://code.whytheluckystiff.net/camping/wiki/TheCampingServer.)
95
- #
96
- # Use this method inside your FastCGI dispatcher:
97
- #
98
- # #!/usr/local/bin/ruby
99
- # require 'rubygems'
100
- # require 'camping/fastcgi'
101
- # Camping::Models::Base.establish_connection :adapter => 'sqlite3', :database => "/path/to/db"
102
- # Camping::FastCGI.serve("/home/why/cvs/camping/examples")
103
- #
104
- def self.serve(path, index=nil)
105
- require 'camping/reloader'
106
- if File.directory? path
107
- fast = Camping::FastCGI.new
108
- script_load = proc do |script|
109
- app = Camping::Reloader.new(script)
110
- fast.mount("/#{app.mount}", app)
111
- app
112
- end
113
- Dir[File.join(path, '*.rb')].each &script_load
114
- fast.mount("/", index) if index
115
-
116
- fast.start do |dir, app|
117
- Dir[File.join(path, dir, '*.rb')].each do |script|
118
- smount = "/" + File.basename(script, '.rb')
119
- script_load[script] unless fast.mounts.has_key? smount
120
- end
121
- end
122
- else
123
- start(Camping::Reloader.new(path))
124
- end
125
- end
126
-
127
- private
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
-
194
- def match(path, mount)
195
- m = path.match(/^#{Regexp::quote mount}(\/|$)/)
196
- if m; m.end(0)
197
- else -1
198
- end
199
- end
200
-
201
- def esc(str)
202
- str.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
203
- end
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
-
243
- end
244
- end
@@ -1,65 +0,0 @@
1
- # == About camping/webrick.rb
2
- #
3
- # For many who have Ruby installed, Camping and WEBrick is a great option.
4
- # It's definitely the easiest configuration, however some performance is sacrificed.
5
- # For better speed, check out Mongrel at http://mongrel.rubyforge.org/, which comes
6
- # with Camping hooks and is supported by the Camping Tool.
7
- require 'camping'
8
- require 'webrick/httpservlet/abstract.rb'
9
-
10
- module WEBrick
11
- # WEBrick::CampingHandler is a very simple handle for hosting Camping apps in
12
- # a WEBrick server. It's used much like any other WEBrick handler.
13
- #
14
- # == Mounting a Camping App
15
- #
16
- # Assuming Camping.goes(:Blog), the Blog application can be mounted alongside
17
- # other WEBrick mounts.
18
- #
19
- # s = WEBrick::HTTPServer.new(:BindAddress => host, :Port => port)
20
- # s.mount "/blog", WEBrick::CampingHandler, Blog
21
- # s.mount_proc("/") { ... }
22
- #
23
- # == How Does it Compare?
24
- #
25
- # Compared to other handlers, WEBrick is well-equipped in terms of features.
26
- #
27
- # * The <tt>X-Sendfile</tt> header is supported, along with etags and
28
- # modification time headers for the file served. Since this handler
29
- # is a subclass of WEBrick::HTTPServlet::DefaultFileHandler, all of its
30
- # logic is used.
31
- # * IO is streaming up and down. When you upload a file, it is streamed to
32
- # the server's filesystem. When you download a file, it is streamed to
33
- # your browser.
34
- #
35
- # While WEBrick is a bit slower than Mongrel and FastCGI options, it's
36
- # a decent choice, for sure!
37
- class CampingHandler < WEBrick::HTTPServlet::DefaultFileHandler
38
- # Creates a CampingHandler, which answers for the application within +klass+.
39
- def initialize(server, klass)
40
- super(server, klass)
41
- @klass = klass
42
- end
43
- # Handler for WEBrick requests (also aliased as do_POST).
44
- def service(req, resp)
45
- controller = @klass.run((req.body and StringIO.new(req.body)), req.meta_vars)
46
- resp.status = controller.status
47
- @local_path = nil
48
- controller.headers.each do |k, v|
49
- if k =~ /^X-SENDFILE$/i
50
- @local_path = v
51
- else
52
- [*v].each do |vi|
53
- resp[k] = vi
54
- end
55
- end
56
- end
57
-
58
- if @local_path
59
- do_GET(req, resp)
60
- else
61
- resp.body = controller.body.to_s
62
- end
63
- end
64
- end
65
- end
@@ -1,55 +0,0 @@
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
-