headius-mongrel 1.1.6.1

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 (71) hide show
  1. data/CHANGELOG +21 -0
  2. data/COPYING +55 -0
  3. data/LICENSE +55 -0
  4. data/Manifest +69 -0
  5. data/README +74 -0
  6. data/Rakefile +202 -0
  7. data/TODO +5 -0
  8. data/bin/mongrel_rails +283 -0
  9. data/examples/builder.rb +29 -0
  10. data/examples/camping/README +3 -0
  11. data/examples/camping/blog.rb +294 -0
  12. data/examples/camping/tepee.rb +149 -0
  13. data/examples/httpd.conf +474 -0
  14. data/examples/mime.yaml +3 -0
  15. data/examples/mongrel.conf +9 -0
  16. data/examples/mongrel_simple_ctrl.rb +92 -0
  17. data/examples/mongrel_simple_service.rb +116 -0
  18. data/examples/monitrc +57 -0
  19. data/examples/random_thrash.rb +19 -0
  20. data/examples/simpletest.rb +52 -0
  21. data/examples/webrick_compare.rb +20 -0
  22. data/ext/http11/ext_help.h +14 -0
  23. data/ext/http11/extconf.rb +6 -0
  24. data/ext/http11/http11.c +402 -0
  25. data/ext/http11/http11_parser.c +1221 -0
  26. data/ext/http11/http11_parser.h +49 -0
  27. data/ext/http11/http11_parser.java.rl +170 -0
  28. data/ext/http11/http11_parser.rl +152 -0
  29. data/ext/http11/http11_parser_common.rl +54 -0
  30. data/ext/http11_java/Http11Service.java +13 -0
  31. data/ext/http11_java/org/jruby/mongrel/Http11.java +353 -0
  32. data/ext/http11_java/org/jruby/mongrel/Http11Parser.java +572 -0
  33. data/lib/mongrel.rb +364 -0
  34. data/lib/mongrel/camping.rb +107 -0
  35. data/lib/mongrel/cgi.rb +181 -0
  36. data/lib/mongrel/command.rb +222 -0
  37. data/lib/mongrel/configurator.rb +388 -0
  38. data/lib/mongrel/const.rb +110 -0
  39. data/lib/mongrel/debug.rb +203 -0
  40. data/lib/mongrel/gems.rb +22 -0
  41. data/lib/mongrel/handlers.rb +468 -0
  42. data/lib/mongrel/header_out.rb +28 -0
  43. data/lib/mongrel/http_request.rb +155 -0
  44. data/lib/mongrel/http_response.rb +163 -0
  45. data/lib/mongrel/init.rb +10 -0
  46. data/lib/mongrel/mime_types.yml +616 -0
  47. data/lib/mongrel/rails.rb +192 -0
  48. data/lib/mongrel/stats.rb +89 -0
  49. data/lib/mongrel/tcphack.rb +18 -0
  50. data/lib/mongrel/uri_classifier.rb +76 -0
  51. data/mongrel-public_cert.pem +20 -0
  52. data/mongrel.gemspec +47 -0
  53. data/setup.rb +1585 -0
  54. data/test/mime.yaml +3 -0
  55. data/test/mongrel.conf +1 -0
  56. data/test/test_cgi_wrapper.rb +26 -0
  57. data/test/test_command.rb +86 -0
  58. data/test/test_conditional.rb +107 -0
  59. data/test/test_configurator.rb +88 -0
  60. data/test/test_debug.rb +25 -0
  61. data/test/test_handlers.rb +126 -0
  62. data/test/test_http11.rb +156 -0
  63. data/test/test_redirect_handler.rb +45 -0
  64. data/test/test_request_progress.rb +100 -0
  65. data/test/test_response.rb +127 -0
  66. data/test/test_stats.rb +35 -0
  67. data/test/test_uriclassifier.rb +261 -0
  68. data/test/test_ws.rb +115 -0
  69. data/test/testhelp.rb +79 -0
  70. data/tools/trickletest.rb +45 -0
  71. metadata +199 -0
data/TODO ADDED
@@ -0,0 +1,5 @@
1
+
2
+ v1.2. Rewrite and merge mongrel cluster and mongrel_rails into something small and maintainable. Remove gem_plugin entirely.
3
+
4
+ v1.1.1. See if Java is setting the server version string in the request properly.
5
+
@@ -0,0 +1,283 @@
1
+ # Copyright (c) 2005 Zed A. Shaw
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+ # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
5
+ # for more information.
6
+
7
+ require 'yaml'
8
+ require 'etc'
9
+
10
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
11
+ require 'mongrel'
12
+ require 'mongrel/rails'
13
+
14
+ Mongrel::Gems.require 'gem_plugin'
15
+
16
+ # require 'ruby-debug'
17
+ # Debugger.start
18
+
19
+ module Mongrel
20
+ class Start < GemPlugin::Plugin "/commands"
21
+ include Mongrel::Command::Base
22
+
23
+ def configure
24
+ options [
25
+ ["-e", "--environment ENV", "Rails environment to run as", :@environment, ENV['RAILS_ENV'] || "development"],
26
+ ["-d", "--daemonize", "Run daemonized in the background", :@daemon, false],
27
+ ['-p', '--port PORT', "Which port to bind to", :@port, 3000],
28
+ ['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"],
29
+ ['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"],
30
+ ['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"],
31
+ ['-n', '--num-processors INT', "Number of processors active before clients denied", :@num_processors, 1024],
32
+ ['-o', '--timeout TIME', "Time to wait (in seconds) before killing a stalled thread", :@timeout, 60],
33
+ ['-t', '--throttle TIME', "Time to pause (in hundredths of a second) between accepting clients", :@throttle, 0],
34
+ ['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil],
35
+ ['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
36
+ ['-r', '--root PATH', "Set the document root (default 'public')", :@docroot, "public"],
37
+ ['-B', '--debug', "Enable debugging mode", :@debug, false],
38
+ ['-C', '--config PATH', "Use a config file", :@config_file, nil],
39
+ ['-S', '--script PATH', "Load the given file as an extra config script", :@config_script, nil],
40
+ ['-G', '--generate PATH', "Generate a config file for use with -C", :@generate, nil],
41
+ ['', '--user USER', "User to run as", :@user, nil],
42
+ ['', '--group GROUP', "Group to run as", :@group, nil],
43
+ ['', '--prefix PATH', "URL prefix for Rails app", :@prefix, nil]
44
+ ]
45
+ end
46
+
47
+ def validate
48
+ if @config_file
49
+ valid_exists?(@config_file, "Config file not there: #@config_file")
50
+ return false unless @valid
51
+ @config_file = File.expand_path(@config_file)
52
+ load_config
53
+ return false unless @valid
54
+ end
55
+
56
+ @cwd = File.expand_path(@cwd)
57
+ valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
58
+
59
+ # Change there to start, then we'll have to come back after daemonize
60
+ Dir.chdir(@cwd)
61
+
62
+ valid?(@prefix[0] == ?/ && @prefix[-1] != ?/, "Prefix must begin with / and not end in /") if @prefix
63
+ valid_dir? File.dirname(@log_file), "Path to log file not valid: #@log_file"
64
+ valid_dir? File.dirname(@pid_file), "Path to pid file not valid: #@pid_file"
65
+ valid_dir? @docroot, "Path to docroot not valid: #@docroot"
66
+ valid_exists? @mime_map, "MIME mapping file does not exist: #@mime_map" if @mime_map
67
+ valid_exists? @config_file, "Config file not there: #@config_file" if @config_file
68
+ valid_dir? File.dirname(@generate), "Problem accessing directory to #@generate" if @generate
69
+ valid_user? @user if @user
70
+ valid_group? @group if @group
71
+
72
+ return @valid
73
+ end
74
+
75
+ def run
76
+ if @generate
77
+ @generate = File.expand_path(@generate)
78
+ STDERR.puts "** Writing config to \"#@generate\"."
79
+ open(@generate, "w") {|f| f.write(settings.to_yaml) }
80
+ STDERR.puts "** Finished. Run \"mongrel_rails start -C #@generate\" to use the config file."
81
+ exit 0
82
+ end
83
+
84
+ config = Mongrel::Rails::RailsConfigurator.new(settings) do
85
+ if defaults[:daemon]
86
+ if File.exist? defaults[:pid_file]
87
+ log "!!! PID file #{defaults[:pid_file]} already exists. Mongrel could be running already. Check your #{defaults[:log_file]} for errors."
88
+ log "!!! Exiting with error. You must stop mongrel and clear the .pid before I'll attempt a start."
89
+ exit 1
90
+ end
91
+
92
+ daemonize
93
+ log "Daemonized, any open files are closed. Look at #{defaults[:pid_file]} and #{defaults[:log_file]} for info."
94
+ log "Settings loaded from #{@config_file} (they override command line)." if @config_file
95
+ end
96
+
97
+ log "Starting Mongrel listening at #{defaults[:host]}:#{defaults[:port]}"
98
+
99
+ listener do
100
+ mime = {}
101
+ if defaults[:mime_map]
102
+ log "Loading additional MIME types from #{defaults[:mime_map]}"
103
+ mime = load_mime_map(defaults[:mime_map], mime)
104
+ end
105
+
106
+ if defaults[:debug]
107
+ log "Installing debugging prefixed filters. Look in log/mongrel_debug for the files."
108
+ debug "/"
109
+ end
110
+
111
+ log "Starting Rails with #{defaults[:environment]} environment..."
112
+ log "Mounting Rails at #{defaults[:prefix]}..." if defaults[:prefix]
113
+ uri defaults[:prefix] || "/", :handler => rails(:mime => mime, :prefix => defaults[:prefix])
114
+ log "Rails loaded."
115
+
116
+ log "Loading any Rails specific GemPlugins"
117
+ load_plugins
118
+
119
+ if defaults[:config_script]
120
+ log "Loading #{defaults[:config_script]} external config script"
121
+ run_config(defaults[:config_script])
122
+ end
123
+
124
+ setup_rails_signals
125
+ end
126
+ end
127
+
128
+ config.run
129
+ config.log "Mongrel #{Mongrel::Const::MONGREL_VERSION} available at #{@address}:#{@port}"
130
+
131
+ if config.defaults[:daemon]
132
+ config.write_pid_file
133
+ else
134
+ config.log "Use CTRL-C to stop."
135
+ end
136
+
137
+ config.join
138
+
139
+ if config.needs_restart
140
+ if RUBY_PLATFORM !~ /mswin/
141
+ cmd = "ruby #{__FILE__} start #{original_args.join(' ')}"
142
+ config.log "Restarting with arguments: #{cmd}"
143
+ config.stop(false, true)
144
+ config.remove_pid_file
145
+
146
+ if config.defaults[:daemon]
147
+ system cmd
148
+ else
149
+ STDERR.puts "Can't restart unless in daemon mode."
150
+ exit 1
151
+ end
152
+ else
153
+ config.log "Win32 does not support restarts. Exiting."
154
+ end
155
+ end
156
+ end
157
+
158
+ def load_config
159
+ settings = {}
160
+ begin
161
+ settings = YAML.load_file(@config_file)
162
+ ensure
163
+ STDERR.puts "** Loading settings from #{@config_file} (they override command line)." unless @daemon || settings[:daemon]
164
+ end
165
+
166
+ settings[:includes] ||= ["mongrel"]
167
+
168
+ # Config file settings will override command line settings
169
+ settings.each do |key, value|
170
+ key = key.to_s
171
+ if config_keys.include?(key)
172
+ key = 'address' if key == 'host'
173
+ self.instance_variable_set("@#{key}", value)
174
+ else
175
+ failure "Unknown configuration setting: #{key}"
176
+ @valid = false
177
+ end
178
+ end
179
+ end
180
+
181
+ def config_keys
182
+ @config_keys ||=
183
+ %w(address host port cwd log_file pid_file environment docroot mime_map daemon debug includes config_script num_processors timeout throttle user group prefix)
184
+ end
185
+
186
+ def settings
187
+ config_keys.inject({}) do |hash, key|
188
+ value = self.instance_variable_get("@#{key}")
189
+ key = 'host' if key == 'address'
190
+ hash[key.to_sym] ||= value
191
+ hash
192
+ end
193
+ end
194
+ end
195
+
196
+ def Mongrel::send_signal(signal, pid_file)
197
+ pid = open(pid_file).read.to_i
198
+ print "Sending #{signal} to Mongrel at PID #{pid}..."
199
+ begin
200
+ Process.kill(signal, pid)
201
+ rescue Errno::ESRCH
202
+ puts "Process does not exist. Not running."
203
+ end
204
+
205
+ puts "Done."
206
+ end
207
+
208
+
209
+ class Stop < GemPlugin::Plugin "/commands"
210
+ include Mongrel::Command::Base
211
+
212
+ def configure
213
+ options [
214
+ ['-c', '--chdir PATH', "Change to dir before starting (will be expanded).", :@cwd, "."],
215
+ ['-f', '--force', "Force the shutdown (kill -9).", :@force, false],
216
+ ['-w', '--wait SECONDS', "Wait SECONDS before forcing shutdown", :@wait, "0"],
217
+ ['-P', '--pid FILE', "Where the PID file is located.", :@pid_file, "log/mongrel.pid"]
218
+ ]
219
+ end
220
+
221
+ def validate
222
+ @cwd = File.expand_path(@cwd)
223
+ valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
224
+
225
+ Dir.chdir @cwd
226
+
227
+ valid_exists? @pid_file, "PID file #@pid_file does not exist. Not running?"
228
+ return @valid
229
+ end
230
+
231
+ def run
232
+ if @force
233
+ @wait.to_i.times do |waiting|
234
+ exit(0) if not File.exist? @pid_file
235
+ sleep 1
236
+ end
237
+
238
+ Mongrel::send_signal("KILL", @pid_file) if File.exist? @pid_file
239
+ else
240
+ Mongrel::send_signal("TERM", @pid_file)
241
+ end
242
+ end
243
+ end
244
+
245
+
246
+ class Restart < GemPlugin::Plugin "/commands"
247
+ include Mongrel::Command::Base
248
+
249
+ def configure
250
+ options [
251
+ ['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, '.'],
252
+ ['-s', '--soft', "Do a soft restart rather than a process exit restart", :@soft, false],
253
+ ['-P', '--pid FILE', "Where the PID file is located", :@pid_file, "log/mongrel.pid"]
254
+ ]
255
+ end
256
+
257
+ def validate
258
+ @cwd = File.expand_path(@cwd)
259
+ valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
260
+
261
+ Dir.chdir @cwd
262
+
263
+ valid_exists? @pid_file, "PID file #@pid_file does not exist. Not running?"
264
+ return @valid
265
+ end
266
+
267
+ def run
268
+ if @soft
269
+ Mongrel::send_signal("HUP", @pid_file)
270
+ else
271
+ Mongrel::send_signal("USR2", @pid_file)
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+
278
+ GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
279
+
280
+
281
+ if not Mongrel::Command::Registry.instance.run ARGV
282
+ exit 1
283
+ end
@@ -0,0 +1,29 @@
1
+ require 'mongrel'
2
+
3
+ class TestPlugin < GemPlugin::Plugin "/handlers"
4
+ include Mongrel::HttpHandlerPlugin
5
+
6
+ def process(request, response)
7
+ STDERR.puts "My options are: #{options.inspect}"
8
+ STDERR.puts "Request Was:"
9
+ STDERR.puts request.params.to_yaml
10
+ end
11
+ end
12
+
13
+ config = Mongrel::Configurator.new :host => "127.0.0.1" do
14
+ load_plugins :includes => ["mongrel"], :excludes => ["rails"]
15
+ daemonize :cwd => Dir.pwd, :log_file => "mongrel.log", :pid_file => "mongrel.pid"
16
+
17
+ listener :port => 3000 do
18
+ uri "/app", :handler => plugin("/handlers/testplugin", :test => "that")
19
+ uri "/app", :handler => Mongrel::DirHandler.new(".")
20
+ load_plugins :includes => ["mongrel", "rails"]
21
+ end
22
+
23
+ trap("INT") { stop }
24
+ run
25
+ end
26
+
27
+ config.join
28
+
29
+
@@ -0,0 +1,3 @@
1
+ To get these examples running, install Camping.
2
+
3
+ Instructions here: http://code.whytheluckystiff.net/camping/
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + "/../../lib"
4
+ require 'rubygems'
5
+ require_gem 'camping', '>=1.4'
6
+ require 'camping/session'
7
+
8
+ Camping.goes :Blog
9
+
10
+ module Blog
11
+ include Camping::Session
12
+ end
13
+
14
+ module Blog::Models
15
+ def self.schema(&block)
16
+ @@schema = block if block_given?
17
+ @@schema
18
+ end
19
+
20
+ class Post < Base; belongs_to :user; end
21
+ class Comment < Base; belongs_to :user; end
22
+ class User < Base; end
23
+ end
24
+
25
+ Blog::Models.schema do
26
+ create_table :blog_posts, :force => true do |t|
27
+ t.column :id, :integer, :null => false
28
+ t.column :user_id, :integer, :null => false
29
+ t.column :title, :string, :limit => 255
30
+ t.column :body, :text
31
+ end
32
+ create_table :blog_users, :force => true do |t|
33
+ t.column :id, :integer, :null => false
34
+ t.column :username, :string
35
+ t.column :password, :string
36
+ end
37
+ create_table :blog_comments, :force => true do |t|
38
+ t.column :id, :integer, :null => false
39
+ t.column :post_id, :integer, :null => false
40
+ t.column :username, :string
41
+ t.column :body, :text
42
+ end
43
+ execute "INSERT INTO blog_users (username, password) VALUES ('admin', 'camping')"
44
+ end
45
+
46
+ module Blog::Controllers
47
+ class Index < R '/'
48
+ def get
49
+ @posts = Post.find :all
50
+ render :index
51
+ end
52
+ end
53
+
54
+ class Add
55
+ def get
56
+ unless @state.user_id.blank?
57
+ @user = User.find @state.user_id
58
+ @post = Post.new
59
+ end
60
+ render :add
61
+ end
62
+ def post
63
+ post = Post.create :title => input.post_title, :body => input.post_body,
64
+ :user_id => @state.user_id
65
+ redirect View, post
66
+ end
67
+ end
68
+
69
+ class Info < R '/info/(\d+)', '/info/(\w+)/(\d+)', '/info', '/info/(\d+)/(\d+)/(\d+)/([\w-]+)'
70
+ def get(*args)
71
+ div do
72
+ code args.inspect; br; br
73
+ code ENV.inspect; br
74
+ code "Link: #{R(Info, 1, 2)}"
75
+ end
76
+ end
77
+ end
78
+
79
+ class View < R '/view/(\d+)'
80
+ def get post_id
81
+ @post = Post.find post_id
82
+ @comments = Models::Comment.find :all, :conditions => ['post_id = ?', post_id]
83
+ render :view
84
+ end
85
+ end
86
+
87
+ class Edit < R '/edit/(\d+)', '/edit'
88
+ def get post_id
89
+ unless @state.user_id.blank?
90
+ @user = User.find @state.user_id
91
+ end
92
+ @post = Post.find post_id
93
+ render :edit
94
+ end
95
+
96
+ def post
97
+ @post = Post.find input.post_id
98
+ @post.update_attributes :title => input.post_title, :body => input.post_body
99
+ redirect View, @post
100
+ end
101
+ end
102
+
103
+ class Comment
104
+ def post
105
+ Models::Comment.create(:username => input.post_username,
106
+ :body => input.post_body, :post_id => input.post_id)
107
+ redirect View, input.post_id
108
+ end
109
+ end
110
+
111
+ class Login
112
+ def post
113
+ @user = User.find :first, :conditions => ['username = ? AND password = ?', input.username, input.password]
114
+
115
+ if @user
116
+ @login = 'login success !'
117
+ @state.user_id = @user.id
118
+ else
119
+ @login = 'wrong user name or password'
120
+ end
121
+ render :login
122
+ end
123
+ end
124
+
125
+ class Logout
126
+ def get
127
+ @state.user_id = nil
128
+ render :logout
129
+ end
130
+ end
131
+
132
+ class Style < R '/styles.css'
133
+ def get
134
+ @headers["Content-Type"] = "text/css; charset=utf-8"
135
+ @body = %{
136
+ body {
137
+ font-family: Utopia, Georga, serif;
138
+ }
139
+ h1.header {
140
+ background-color: #fef;
141
+ margin: 0; padding: 10px;
142
+ }
143
+ div.content {
144
+ padding: 10px;
145
+ }
146
+ }
147
+ end
148
+ end
149
+ end
150
+
151
+ module Blog::Views
152
+
153
+ def layout
154
+ html do
155
+ head do
156
+ title 'blog'
157
+ link :rel => 'stylesheet', :type => 'text/css',
158
+ :href => '/styles.css', :media => 'screen'
159
+ end
160
+ body do
161
+ h1.header { a 'blog', :href => R(Index) }
162
+ div.content do
163
+ self << yield
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ def index
170
+ if @posts.empty?
171
+ p 'No posts found.'
172
+ p { a 'Add', :href => R(Add) }
173
+ else
174
+ for post in @posts
175
+ _post(post)
176
+ end
177
+ end
178
+ end
179
+
180
+ def login
181
+ p { b @login }
182
+ p { a 'Continue', :href => R(Add) }
183
+ end
184
+
185
+ def logout
186
+ p "You have been logged out."
187
+ p { a 'Continue', :href => R(Index) }
188
+ end
189
+
190
+ def add
191
+ if @user
192
+ _form(post, :action => R(Add))
193
+ else
194
+ _login
195
+ end
196
+ end
197
+
198
+ def edit
199
+ if @user
200
+ _form(post, :action => R(Edit))
201
+ else
202
+ _login
203
+ end
204
+ end
205
+
206
+ def view
207
+ _post(post)
208
+
209
+ p "Comment for this post:"
210
+ for c in @comments
211
+ h1 c.username
212
+ p c.body
213
+ end
214
+
215
+ form :action => R(Comment), :method => 'post' do
216
+ label 'Name', :for => 'post_username'; br
217
+ input :name => 'post_username', :type => 'text'; br
218
+ label 'Comment', :for => 'post_body'; br
219
+ textarea :name => 'post_body' do; end; br
220
+ input :type => 'hidden', :name => 'post_id', :value => post.id
221
+ input :type => 'submit'
222
+ end
223
+ end
224
+
225
+ # partials
226
+ def _login
227
+ form :action => R(Login), :method => 'post' do
228
+ label 'Username', :for => 'username'; br
229
+ input :name => 'username', :type => 'text'; br
230
+
231
+ label 'Password', :for => 'password'; br
232
+ input :name => 'password', :type => 'text'; br
233
+
234
+ input :type => 'submit', :name => 'login', :value => 'Login'
235
+ end
236
+ end
237
+
238
+ def _post(post)
239
+ h1 post.title
240
+ p post.body
241
+ p do
242
+ a "Edit", :href => R(Edit, post)
243
+ a "View", :href => R(View, post)
244
+ end
245
+ end
246
+
247
+ def _form(post, opts)
248
+ p do
249
+ text "You are logged in as #{@user.username} | "
250
+ a 'Logout', :href => R(Logout)
251
+ end
252
+ form({:method => 'post'}.merge(opts)) do
253
+ label 'Title', :for => 'post_title'; br
254
+ input :name => 'post_title', :type => 'text',
255
+ :value => post.title; br
256
+
257
+ label 'Body', :for => 'post_body'; br
258
+ textarea post.body, :name => 'post_body'; br
259
+
260
+ input :type => 'hidden', :name => 'post_id', :value => post.id
261
+ input :type => 'submit'
262
+ end
263
+ end
264
+ end
265
+
266
+ def Blog.create
267
+ Camping::Models::Session.create_schema
268
+ unless Blog::Models::Post.table_exists?
269
+ ActiveRecord::Schema.define(&Blog::Models.schema)
270
+ end
271
+ end
272
+
273
+ if __FILE__ == $0
274
+ require 'mongrel/camping'
275
+
276
+ Blog::Models::Base.establish_connection :adapter => 'sqlite3', :database => 'blog.db'
277
+ Blog::Models::Base.logger = Logger.new('camping.log')
278
+ Blog::Models::Base.threaded_connections=false
279
+ Blog.create
280
+
281
+ # Use the Configurator as an example rather than Mongrel::Camping.start
282
+ config = Mongrel::Configurator.new :host => "0.0.0.0" do
283
+ listener :port => 3002 do
284
+ uri "/blog", :handler => Mongrel::Camping::CampingHandler.new(Blog)
285
+ uri "/favicon", :handler => Mongrel::Error404Handler.new("")
286
+ trap("INT") { stop }
287
+ run
288
+ end
289
+ end
290
+
291
+ puts "** Blog example is running at http://localhost:3002/blog"
292
+ puts "** Default username is `admin', password is `camping'"
293
+ config.join
294
+ end