mongrel 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/COPYING +504 -0
  2. data/LICENSE +504 -0
  3. data/README +117 -0
  4. data/Rakefile +30 -0
  5. data/doc/rdoc/classes/Mongrel.html +144 -0
  6. data/doc/rdoc/classes/Mongrel/Error404Handler.html +171 -0
  7. data/doc/rdoc/classes/Mongrel/Error404Handler.src/M000023.html +18 -0
  8. data/doc/rdoc/classes/Mongrel/Error404Handler.src/M000024.html +18 -0
  9. data/doc/rdoc/classes/Mongrel/HeaderOut.html +167 -0
  10. data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000013.html +18 -0
  11. data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000014.html +21 -0
  12. data/doc/rdoc/classes/Mongrel/HttpHandler.html +159 -0
  13. data/doc/rdoc/classes/Mongrel/HttpHandler.src/M000019.html +17 -0
  14. data/doc/rdoc/classes/Mongrel/HttpParser.html +271 -0
  15. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000001.html +28 -0
  16. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000002.html +29 -0
  17. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000003.html +29 -0
  18. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000004.html +41 -0
  19. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000005.html +27 -0
  20. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000006.html +27 -0
  21. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000007.html +28 -0
  22. data/doc/rdoc/classes/Mongrel/HttpRequest.html +177 -0
  23. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000025.html +30 -0
  24. data/doc/rdoc/classes/Mongrel/HttpResponse.html +202 -0
  25. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000020.html +21 -0
  26. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000021.html +20 -0
  27. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000022.html +25 -0
  28. data/doc/rdoc/classes/Mongrel/HttpServer.html +336 -0
  29. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html +26 -0
  30. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html +58 -0
  31. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000010.html +22 -0
  32. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000011.html +18 -0
  33. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html +18 -0
  34. data/doc/rdoc/classes/Mongrel/URIClassifier.html +257 -0
  35. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000015.html +54 -0
  36. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000016.html +50 -0
  37. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000017.html +36 -0
  38. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000018.html +73 -0
  39. data/doc/rdoc/created.rid +1 -0
  40. data/doc/rdoc/files/COPYING.html +756 -0
  41. data/doc/rdoc/files/LICENSE.html +756 -0
  42. data/doc/rdoc/files/README.html +273 -0
  43. data/doc/rdoc/files/ext/http11/http11_c.html +101 -0
  44. data/doc/rdoc/files/lib/mongrel_rb.html +111 -0
  45. data/doc/rdoc/fr_class_index.html +35 -0
  46. data/doc/rdoc/fr_file_index.html +31 -0
  47. data/doc/rdoc/fr_method_index.html +51 -0
  48. data/doc/rdoc/index.html +24 -0
  49. data/doc/rdoc/rdoc-style.css +208 -0
  50. data/examples/camping/blog.rb +300 -0
  51. data/examples/camping/tepee.rb +168 -0
  52. data/examples/simpletest.rb +16 -0
  53. data/examples/webrick_compare.rb +20 -0
  54. data/ext/http11/MANIFEST +0 -0
  55. data/ext/http11/ext_help.h +14 -0
  56. data/ext/http11/extconf.rb +6 -0
  57. data/ext/http11/http11.c +436 -0
  58. data/ext/http11/http11_parser.c +918 -0
  59. data/ext/http11/http11_parser.h +37 -0
  60. data/ext/http11/tst.h +40 -0
  61. data/ext/http11/tst_cleanup.c +24 -0
  62. data/ext/http11/tst_delete.c +146 -0
  63. data/ext/http11/tst_grow_node_free_list.c +38 -0
  64. data/ext/http11/tst_init.c +41 -0
  65. data/ext/http11/tst_insert.c +192 -0
  66. data/ext/http11/tst_search.c +54 -0
  67. data/lib/mongrel.rb +298 -0
  68. data/setup.rb +1360 -0
  69. data/test/test_http11.rb +38 -0
  70. data/test/test_response.rb +44 -0
  71. data/test/test_uriclassifier.rb +104 -0
  72. data/test/test_ws.rb +33 -0
  73. data/tools/rakehelp.rb +99 -0
  74. metadata +132 -0
@@ -0,0 +1,35 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Classes
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Classes</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Classes</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/Mongrel.html">Mongrel</a><br />
24
+ <a href="classes/Mongrel/Error404Handler.html">Mongrel::Error404Handler</a><br />
25
+ <a href="classes/Mongrel/HeaderOut.html">Mongrel::HeaderOut</a><br />
26
+ <a href="classes/Mongrel/HttpHandler.html">Mongrel::HttpHandler</a><br />
27
+ <a href="classes/Mongrel/HttpParser.html">Mongrel::HttpParser</a><br />
28
+ <a href="classes/Mongrel/HttpRequest.html">Mongrel::HttpRequest</a><br />
29
+ <a href="classes/Mongrel/HttpResponse.html">Mongrel::HttpResponse</a><br />
30
+ <a href="classes/Mongrel/HttpServer.html">Mongrel::HttpServer</a><br />
31
+ <a href="classes/Mongrel/URIClassifier.html">Mongrel::URIClassifier</a><br />
32
+ </div>
33
+ </div>
34
+ </body>
35
+ </html>
@@ -0,0 +1,31 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Files
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Files</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Files</h1>
22
+ <div id="index-entries">
23
+ <a href="files/COPYING.html">COPYING</a><br />
24
+ <a href="files/LICENSE.html">LICENSE</a><br />
25
+ <a href="files/README.html">README</a><br />
26
+ <a href="files/ext/http11/http11_c.html">ext/http11/http11.c</a><br />
27
+ <a href="files/lib/mongrel_rb.html">lib/mongrel.rb</a><br />
28
+ </div>
29
+ </div>
30
+ </body>
31
+ </html>
@@ -0,0 +1,51 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Methods
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Methods</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Methods</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/Mongrel/HeaderOut.html#M000014">[]= (Mongrel::HeaderOut)</a><br />
24
+ <a href="classes/Mongrel/HttpParser.html#M000005">error? (Mongrel::HttpParser)</a><br />
25
+ <a href="classes/Mongrel/HttpParser.html#M000004">execute (Mongrel::HttpParser)</a><br />
26
+ <a href="classes/Mongrel/HttpParser.html#M000003">finish (Mongrel::HttpParser)</a><br />
27
+ <a href="classes/Mongrel/HttpResponse.html#M000022">finished (Mongrel::HttpResponse)</a><br />
28
+ <a href="classes/Mongrel/HttpParser.html#M000006">finished? (Mongrel::HttpParser)</a><br />
29
+ <a href="classes/Mongrel/Error404Handler.html#M000023">new (Mongrel::Error404Handler)</a><br />
30
+ <a href="classes/Mongrel/HttpServer.html#M000008">new (Mongrel::HttpServer)</a><br />
31
+ <a href="classes/Mongrel/HttpRequest.html#M000025">new (Mongrel::HttpRequest)</a><br />
32
+ <a href="classes/Mongrel/HttpResponse.html#M000020">new (Mongrel::HttpResponse)</a><br />
33
+ <a href="classes/Mongrel/URIClassifier.html#M000015">new (Mongrel::URIClassifier)</a><br />
34
+ <a href="classes/Mongrel/HttpParser.html#M000001">new (Mongrel::HttpParser)</a><br />
35
+ <a href="classes/Mongrel/HeaderOut.html#M000013">new (Mongrel::HeaderOut)</a><br />
36
+ <a href="classes/Mongrel/HttpParser.html#M000007">nread (Mongrel::HttpParser)</a><br />
37
+ <a href="classes/Mongrel/Error404Handler.html#M000024">process (Mongrel::Error404Handler)</a><br />
38
+ <a href="classes/Mongrel/HttpHandler.html#M000019">process (Mongrel::HttpHandler)</a><br />
39
+ <a href="classes/Mongrel/HttpServer.html#M000009">process_client (Mongrel::HttpServer)</a><br />
40
+ <a href="classes/Mongrel/HttpServer.html#M000011">register (Mongrel::HttpServer)</a><br />
41
+ <a href="classes/Mongrel/URIClassifier.html#M000016">register (Mongrel::URIClassifier)</a><br />
42
+ <a href="classes/Mongrel/HttpParser.html#M000002">reset (Mongrel::HttpParser)</a><br />
43
+ <a href="classes/Mongrel/URIClassifier.html#M000018">resolve (Mongrel::URIClassifier)</a><br />
44
+ <a href="classes/Mongrel/HttpServer.html#M000010">run (Mongrel::HttpServer)</a><br />
45
+ <a href="classes/Mongrel/HttpResponse.html#M000021">start (Mongrel::HttpResponse)</a><br />
46
+ <a href="classes/Mongrel/URIClassifier.html#M000017">unregister (Mongrel::URIClassifier)</a><br />
47
+ <a href="classes/Mongrel/HttpServer.html#M000012">unregister (Mongrel::HttpServer)</a><br />
48
+ </div>
49
+ </div>
50
+ </body>
51
+ </html>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ RDoc Documentation
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>RDoc Documentation</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+ <frameset rows="20%, 80%">
17
+ <frameset cols="25%,35%,45%">
18
+ <frame src="fr_file_index.html" title="Files" name="Files" />
19
+ <frame src="fr_class_index.html" name="Classes" />
20
+ <frame src="fr_method_index.html" name="Methods" />
21
+ </frameset>
22
+ <frame src="files/README.html" name="docwin" />
23
+ </frameset>
24
+ </html>
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + "/../../lib"
4
+ require 'rubygems'
5
+ require 'camping'
6
+
7
+ Camping.goes :Blog
8
+
9
+ module Blog::Models
10
+ def self.schema(&block)
11
+ @@schema = block if block_given?
12
+ @@schema
13
+ end
14
+
15
+ class Post < Base; belongs_to :user; end
16
+ class Comment < Base; belongs_to :user; end
17
+ class User < Base; end
18
+ end
19
+
20
+ Blog::Models.schema do
21
+ create_table :blog_posts, :force => true do |t|
22
+ t.column :id, :integer, :null => false
23
+ t.column :user_id, :integer, :null => false
24
+ t.column :title, :string, :limit => 255
25
+ t.column :body, :text
26
+ end
27
+ create_table :blog_users, :force => true do |t|
28
+ t.column :id, :integer, :null => false
29
+ t.column :username, :string
30
+ t.column :password, :string
31
+ end
32
+ create_table :blog_comments, :force => true do |t|
33
+ t.column :id, :integer, :null => false
34
+ t.column :post_id, :integer, :null => false
35
+ t.column :username, :string
36
+ t.column :body, :text
37
+ end
38
+ execute "INSERT INTO blog_users (username, password) VALUES ('admin', 'camping')"
39
+ end
40
+
41
+ module Blog::Controllers
42
+ class Index < R '/'
43
+ def get
44
+ @posts = Post.find :all
45
+ render :index
46
+ end
47
+ end
48
+
49
+ class Add
50
+ def get
51
+ unless cookies.user_id.blank?
52
+ @session = User.find cookies.user_id
53
+ @post = Post.new
54
+ end
55
+ render :add
56
+ end
57
+ def post
58
+ post = Post.create :title => input.post_title, :body => input.post_body,
59
+ :user_id => @cookies.user_id
60
+ redirect View, post
61
+ end
62
+ end
63
+
64
+ class Info < R '/info/(\d+)', '/info/(\w+)/(\d+)', '/info', '/info/(\d+)/(\d+)/(\d+)/([\w-]+)'
65
+ def get(*args)
66
+ div do
67
+ code args.inspect; br; br
68
+ code ENV.inspect; br
69
+ code "Link: #{R(Info, 1, 2)}"
70
+ end
71
+ end
72
+ end
73
+
74
+ class View < R '/view/(\d+)'
75
+ def get post_id
76
+ @post = Post.find post_id
77
+ @comments = Models::Comment.find :all, :conditions => ['post_id = ?', post_id]
78
+ render :view
79
+ end
80
+ end
81
+
82
+ class Edit < R '/edit/(\d+)', '/edit'
83
+ def get post_id
84
+ unless cookies.user_id.blank?
85
+ @session = User.find cookies.user_id
86
+ end
87
+ @post = Post.find post_id
88
+ render :edit
89
+ end
90
+
91
+ def post
92
+ @post = Post.find input.post_id
93
+ @post.update_attributes :title => input.post_title, :body => input.post_body
94
+ redirect View, @post
95
+ end
96
+ end
97
+
98
+ class Comment
99
+ def post
100
+ Models::Comment.create(:username => input.post_username,
101
+ :body => input.post_body, :post_id => input.post_id)
102
+ redirect View, input.post_id
103
+ end
104
+ end
105
+
106
+ class Login
107
+ def post
108
+ @user = User.find :first, :conditions => ['username = ? AND password = ?', input.username, input.password]
109
+
110
+ if @user
111
+ @login = 'login success !'
112
+ cookies.user_id = @user.id
113
+ else
114
+ @login = 'wrong user name or password'
115
+ end
116
+ render :login
117
+ end
118
+ end
119
+
120
+ class Logout
121
+ def get
122
+ cookies.user_id = nil
123
+ render :logout
124
+ end
125
+ end
126
+
127
+ class Style < R '/styles.css'
128
+ def get
129
+ @headers["Content-Type"] = "text/css; charset=utf-8"
130
+ @body = %{
131
+ body {
132
+ font-family: Utopia, Georga, serif;
133
+ }
134
+ h1.header {
135
+ background-color: #fef;
136
+ margin: 0; padding: 10px;
137
+ }
138
+ div.content {
139
+ padding: 10px;
140
+ }
141
+ }
142
+ end
143
+ end
144
+ end
145
+
146
+ module Blog::Views
147
+
148
+ def layout
149
+ html do
150
+ head do
151
+ title 'blog'
152
+ link :rel => 'stylesheet', :type => 'text/css',
153
+ :href => '/styles.css', :media => 'screen'
154
+ end
155
+ body do
156
+ h1.header { a 'blog', :href => R(Index) }
157
+ div.content do
158
+ self << yield
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ def index
165
+ if @posts.empty?
166
+ p 'No posts found.'
167
+ p { a 'Add', :href => R(Add) }
168
+ else
169
+ for post in @posts
170
+ _post(post)
171
+ end
172
+ end
173
+ end
174
+
175
+ def login
176
+ p { b @login }
177
+ p { a 'Continue', :href => R(Add) }
178
+ end
179
+
180
+ def logout
181
+ p "You have been logged out."
182
+ p { a 'Continue', :href => R(Index) }
183
+ end
184
+
185
+ def add
186
+ if @session
187
+ _form(post, :action => R(Add))
188
+ else
189
+ _login
190
+ end
191
+ end
192
+
193
+ def edit
194
+ if @session
195
+ _form(post, :action => R(Edit))
196
+ else
197
+ _login
198
+ end
199
+ end
200
+
201
+ def view
202
+ _post(post)
203
+
204
+ p "Comment for this post:"
205
+ for c in @comments
206
+ h1 c.username
207
+ p c.body
208
+ end
209
+
210
+ form :action => R(Comment), :method => 'post' do
211
+ label 'Name', :for => 'post_username'; br
212
+ input :name => 'post_username', :type => 'text'; br
213
+ label 'Comment', :for => 'post_body'; br
214
+ textarea :name => 'post_body' do; end; br
215
+ input :type => 'hidden', :name => 'post_id', :value => post.id
216
+ input :type => 'submit'
217
+ end
218
+ end
219
+
220
+ # partials
221
+ def _login
222
+ form :action => R(Login), :method => 'post' do
223
+ label 'Username', :for => 'username'; br
224
+ input :name => 'username', :type => 'text'; br
225
+
226
+ label 'Password', :for => 'password'; br
227
+ input :name => 'password', :type => 'text'; br
228
+
229
+ input :type => 'submit', :name => 'login', :value => 'Login'
230
+ end
231
+ end
232
+
233
+ def _post(post)
234
+ h1 post.title
235
+ p post.body
236
+ p do
237
+ a "Edit", :href => R(Edit, post)
238
+ a "View", :href => R(View, post)
239
+ end
240
+ end
241
+
242
+ def _form(post, opts)
243
+ p do
244
+ text "You are logged in as #{@session.username} | "
245
+ a 'Logout', :href => R(Logout)
246
+ end
247
+ form({:method => 'post'}.merge(opts)) do
248
+ label 'Title', :for => 'post_title'; br
249
+ input :name => 'post_title', :type => 'text',
250
+ :value => post.title; br
251
+
252
+ label 'Body', :for => 'post_body'; br
253
+ textarea post.body, :name => 'post_body'; br
254
+
255
+ input :type => 'hidden', :name => 'post_id', :value => post.id
256
+ input :type => 'submit'
257
+ end
258
+ end
259
+ end
260
+
261
+ def Blog.create
262
+ unless Blog::Models::Post.table_exists?
263
+ ActiveRecord::Schema.define(&Blog::Models.schema)
264
+ puts "** The blog.db file has been created."
265
+ puts "** When adding/editing posts -- username: admin, password: camping"
266
+ end
267
+ end
268
+
269
+ if __FILE__ == $0
270
+ require 'thread'
271
+
272
+ class CampingHandler < Mongrel::HttpHandler
273
+ def initialize(klass)
274
+ @klass = klass
275
+ end
276
+ def process(request, response)
277
+ req = StringIO.new(request.body)
278
+ controller = @klass.run(req, request.params)
279
+ response.start(controller.status) do |head,out|
280
+ controller.headers.each do |k, v|
281
+ [*v].each do |vi|
282
+ head[k] = vi
283
+ end
284
+ end
285
+ out << controller.body
286
+ end
287
+ end
288
+ end
289
+
290
+ Blog::Models::Base.establish_connection :adapter => 'sqlite3', :database => 'blog.db'
291
+ Blog::Models::Base.logger = Logger.new('camping.log')
292
+ Blog::Models::Base.threaded_connections=false
293
+ Blog.create
294
+
295
+ h = Mongrel::HttpServer.new("0.0.0.0", "3000")
296
+ puts "** Blog example is running at http://localhost:3000/blog"
297
+ h.register("/blog", CampingHandler.new(Blog))
298
+ h.register("/favicon.ico", Mongrel::Error404Handler.new(""))
299
+ h.run.join
300
+ end