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
data/examples/blog.rb CHANGED
@@ -1,171 +1,178 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.dirname(__FILE__) + "/../../lib"
3
+ $:.unshift File.dirname(__FILE__) + '/../lib'
4
4
  require 'camping'
5
+ require 'camping/ar'
5
6
  require 'camping/session'
6
-
7
+ require 'redcloth'
8
+
7
9
  Camping.goes :Blog
8
10
 
9
11
  module Blog
10
- include Camping::Session
11
- end
12
+ include Camping::Session
12
13
 
13
- module Blog::Models
14
- class Post < Base; belongs_to :user; end
14
+ module Models
15
+ class Post < Base
16
+ belongs_to :user
17
+
18
+ before_save do |record|
19
+ cloth = RedCloth.new(record.body)
20
+ cloth.hard_breaks = false
21
+ record.html_body = cloth.to_html
22
+ end
23
+ end
24
+
15
25
  class Comment < Base; belongs_to :user; end
16
26
  class User < Base; end
17
27
 
18
- class CreateTheBasics < V 1.0
28
+ class BasicFields < V 1.1
19
29
  def self.up
20
30
  create_table :blog_posts, :force => true do |t|
21
- t.column :id, :integer, :null => false
22
- t.column :user_id, :integer, :null => false
23
- t.column :title, :string, :limit => 255
24
- t.column :body, :text
31
+ t.integer :user_id, :null => false
32
+ t.string :title, :limit => 255
33
+ t.text :body, :html_body
34
+ t.timestamps
25
35
  end
26
36
  create_table :blog_users, :force => true do |t|
27
- t.column :id, :integer, :null => false
28
- t.column :username, :string
29
- t.column :password, :string
37
+ t.string :username, :password
30
38
  end
31
39
  create_table :blog_comments, :force => true do |t|
32
- t.column :id, :integer, :null => false
33
- t.column :post_id, :integer, :null => false
34
- t.column :username, :string
35
- t.column :body, :text
40
+ t.integer :post_id, :null => false
41
+ t.string :username
42
+ t.text :body, :html_body
43
+ t.timestamps
36
44
  end
37
45
  User.create :username => 'admin', :password => 'camping'
38
46
  end
47
+
39
48
  def self.down
40
49
  drop_table :blog_posts
41
50
  drop_table :blog_users
42
51
  drop_table :blog_comments
43
52
  end
44
53
  end
45
- end
54
+ end
46
55
 
47
- module Blog::Controllers
48
- class Index < R '/'
49
- def get
50
- @posts = Post.find :all
51
- render :index
52
- end
53
- end
54
-
55
- class Add
56
- def get
57
- unless @state.user_id.blank?
58
- @user = User.find @state.user_id
59
- @post = Post.new
60
- end
61
- render :add
62
- end
63
- def post
64
- unless @state.user_id.blank?
65
- post = Post.create :title => input.post_title, :body => input.post_body,
66
- :user_id => @state.user_id
67
- redirect View, post
68
- end
69
- end
56
+ module Controllers
57
+ class Index
58
+ def get
59
+ @posts = Post.all(:order => 'updated_at DESC')
60
+ render :index
61
+ end
70
62
  end
71
63
 
72
- class Info < R '/info/(\d+)', '/info/(\w+)/(\d+)', '/info', '/info/(\d+)/(\d+)/(\d+)/([\w-]+)'
73
- def get(*args)
74
- div do
75
- code args.inspect; br; br
76
- code @env.inspect; br
77
- code "Link: #{R(Info, 1, 2)}"
78
- end
79
- end
64
+ class PostNew
65
+ def get
66
+ require_login!
67
+ @post = Post.new
68
+ render :add
69
+ end
70
+
71
+ def post
72
+ require_login!
73
+ post = Post.create(:title => input.post_title, :body => input.post_body,
74
+ :user_id => @state.user_id)
75
+ redirect PostN, post
76
+ end
80
77
  end
81
78
 
82
- class View < R '/view/(\d+)'
83
- def get post_id
84
- @post = Post.find post_id
85
- @comments = Models::Comment.find :all, :conditions => ['post_id = ?', post_id]
86
- render :view
87
- end
88
- end
89
-
90
- class Edit < R '/edit/(\d+)', '/edit'
91
- def get post_id
92
- unless @state.user_id.blank?
93
- @user = User.find @state.user_id
94
- end
95
- @post = Post.find post_id
96
- render :edit
97
- end
98
-
99
- def post
100
- unless @state.user_id.blank?
101
- @post = Post.find input.post_id
102
- @post.update_attributes :title => input.post_title, :body => input.post_body
103
- redirect View, @post
104
- end
105
- end
79
+ class PostN
80
+ def get(post_id)
81
+ @post = Post.find(post_id)
82
+ render :view
83
+ end
106
84
  end
107
-
108
- class Comment
109
- def post
110
- Models::Comment.create(:username => input.post_username,
111
- :body => input.post_body, :post_id => input.post_id)
112
- redirect View, input.post_id
113
- end
85
+
86
+ class Edit < R '/post/(\d+)/edit'
87
+ def get(post_id)
88
+ require_login!
89
+ @post = Post.find(post_id)
90
+ render :edit
91
+ end
92
+
93
+ def post(post_id)
94
+ require_login!
95
+ @post = Post.find(post_id)
96
+ @post.update_attributes :title => input.post_title, :body => input.post_body
97
+ redirect PostN, @post
98
+ end
114
99
  end
115
-
100
+
116
101
  class Login
117
- def post
118
- @user = User.find :first, :conditions => ['username = ? AND password = ?', input.username, input.password]
119
-
120
- if @user
121
- @login = 'login success !'
122
- @state.user_id = @user.id
123
- else
124
- @login = 'wrong user name or password'
125
- end
126
- render :login
102
+ def get
103
+ render :login
104
+ end
105
+
106
+ def post
107
+ @user = User.find_by_username_and_password(input.username, input.password)
108
+
109
+ if @user
110
+ @state.user_id = @user.id
111
+ redirect R(Index)
112
+ else
113
+ @info = 'Wrong username or password.'
127
114
  end
115
+
116
+ render :login
117
+ end
128
118
  end
129
-
119
+
130
120
  class Logout
131
- def get
132
- @state.user_id = nil
133
- render :logout
134
- end
135
- end
136
-
137
- class Style < R '/styles.css'
138
- def get
139
- @headers["Content-Type"] = "text/css; charset=utf-8"
140
- @body = %{
141
- body {
142
- font-family: Utopia, Georga, serif;
143
- }
144
- h1.header {
145
- background-color: #fef;
146
- margin: 0; padding: 10px;
147
- }
148
- div.content {
149
- padding: 10px;
150
- }
151
- }
152
- end
121
+ def get
122
+ @state.user_id = nil
123
+ redirect Index
124
+ end
153
125
  end
154
- end
155
126
 
156
- module Blog::Views
127
+ class Style < R '/styles\.css'
128
+ STYLE = File.read(__FILE__).gsub(/.*__END__/m, '')
129
+
130
+ def get
131
+ @headers['Content-Type'] = 'text/css; charset=utf-8'
132
+ STYLE
133
+ end
134
+ end
135
+ end
136
+
137
+ module Helpers
138
+ def logged_in?
139
+ !!@state.user_id
140
+ end
141
+
142
+ def require_login!
143
+ unless logged_in?
144
+ redirect Controllers::Login
145
+ throw :halt
146
+ end
147
+ end
148
+ end
157
149
 
150
+ module Views
158
151
  def layout
159
152
  html do
160
153
  head do
161
- title 'blog'
154
+ title 'My Blog'
162
155
  link :rel => 'stylesheet', :type => 'text/css',
163
- :href => '/styles.css', :media => 'screen'
156
+ :href => '/styles.css', :media => 'screen'
164
157
  end
165
158
  body do
166
- h1.header { a 'blog', :href => R(Index) }
167
- div.content do
168
- self << yield
159
+ h1 { a 'My Blog', :href => R(Index) }
160
+
161
+ div.wrapper! do
162
+ text yield
163
+ end
164
+
165
+ hr
166
+
167
+ p.footer! do
168
+ if logged_in?
169
+ _admin_menu
170
+ else
171
+ a 'Login', :href => R(Login)
172
+ text ' to the adminpanel'
173
+ end
174
+ text ' &ndash; Powered by '
175
+ a 'Camping', :href => 'http://camping.rubyforge.org/'
169
176
  end
170
177
  end
171
178
  end
@@ -173,99 +180,191 @@ module Blog::Views
173
180
 
174
181
  def index
175
182
  if @posts.empty?
176
- p 'No posts found.'
177
- p { a 'Add', :href => R(Add) }
183
+ h2 'No posts'
184
+ p do
185
+ text 'Could not find any posts. Feel free to '
186
+ a 'add one', :href => R(PostNew)
187
+ text ' yourself. '
188
+ end
178
189
  else
179
- for post in @posts
190
+ @posts.each do |post|
180
191
  _post(post)
181
192
  end
182
193
  end
183
194
  end
184
195
 
185
196
  def login
186
- p { b @login }
187
- p { a 'Continue', :href => R(Add) }
188
- end
197
+ h2 'Login'
198
+ p.info @info if @info
199
+
200
+ form :action => R(Login), :method => 'post' do
201
+ input :name => 'to', :type => 'hidden', :value => @to if @to
202
+
203
+ label 'Username', :for => 'username'
204
+ input :name => 'username', :id => 'username', :type => 'text'
189
205
 
190
- def logout
191
- p "You have been logged out."
192
- p { a 'Continue', :href => R(Index) }
206
+ label 'Password', :for => 'password'
207
+ input :name => 'password', :id => 'password', :type => 'password'
208
+
209
+ input :type => 'submit', :class => 'submit', :value => 'Login'
210
+ end
193
211
  end
194
212
 
195
213
  def add
196
- if @user
197
- _form(@post, :action => R(Add))
198
- else
199
- _login
200
- end
214
+ _form(@post, :action => R(PostNew))
201
215
  end
202
216
 
203
217
  def edit
204
- if @user
205
- _form(@post, :action => R(Edit))
206
- else
207
- _login
208
- end
218
+ _form(@post, :action => R(Edit, @post))
209
219
  end
210
220
 
211
221
  def view
212
- _post(@post)
213
-
214
- p "Comment for this post:"
215
- for c in @comments
216
- h1 c.username
217
- p c.body
218
- end
219
-
220
- form :action => R(Comment), :method => 'post' do
221
- label 'Name', :for => 'post_username'; br
222
- input :name => 'post_username', :type => 'text'; br
223
- label 'Comment', :for => 'post_body'; br
224
- textarea :name => 'post_body' do; end; br
225
- input :type => 'hidden', :name => 'post_id', :value => @post.id
226
- input :type => 'submit'
227
- end
222
+ _post(@post)
228
223
  end
229
224
 
230
225
  # partials
231
- def _login
232
- form :action => R(Login), :method => 'post' do
233
- label 'Username', :for => 'username'; br
234
- input :name => 'username', :type => 'text'; br
235
-
236
- label 'Password', :for => 'password'; br
237
- input :name => 'password', :type => 'text'; br
238
-
239
- input :type => 'submit', :name => 'login', :value => 'Login'
240
- end
226
+ def _admin_menu
227
+ text [['Log out', R(Logout)], ['New', R(PostNew)]].map { |name, to|
228
+ capture { a name, :href => to}
229
+ }.join(' &ndash; ')
241
230
  end
242
231
 
243
232
  def _post(post)
244
- h1 post.title
245
- p post.body
246
- p do
247
- [a("Edit", :href => R(Edit, post)), a("View", :href => R(View, post))].join " | "
233
+ h2 { a post.title, :href => R(PostN, post) }
234
+ p.info do
235
+ text "Written by <strong>#{post.user.username}</strong> "
236
+ text post.updated_at.strftime('%B %M, %Y @ %H:%M ')
237
+ _post_menu(post)
238
+ end
239
+ text post.html_body
240
+ end
241
+
242
+ def _post_menu(post)
243
+ if logged_in?
244
+ a '(edit)', :href => R(Edit, post)
248
245
  end
249
246
  end
250
247
 
251
248
  def _form(post, opts)
252
- p { "You are logged in as #{@user.username} | #{a 'Logout', :href => R(Logout)}" }
253
249
  form({:method => 'post'}.merge(opts)) do
254
- label 'Title', :for => 'post_title'; br
255
- input :name => 'post_title', :type => 'text',
256
- :value => post.title; br
250
+ label 'Title', :for => 'post_title'
251
+ input :name => 'post_title', :id => 'post_title', :type => 'text',
252
+ :value => post.title
257
253
 
258
- label 'Body', :for => 'post_body'; br
259
- textarea post.body, :name => 'post_body'; br
254
+ label 'Body', :for => 'post_body'
255
+ textarea post.body, :name => 'post_body', :id => 'post_body'
260
256
 
261
257
  input :type => 'hidden', :name => 'post_id', :value => post.id
262
- input :type => 'submit'
258
+ input :type => 'submit', :class => 'submit', :value => 'Submit'
263
259
  end
264
260
  end
261
+ end
265
262
  end
266
-
263
+
267
264
  def Blog.create
268
- Camping::Models::Session.create_schema
269
- Blog::Models.create_schema :assume => (Blog::Models::Post.table_exists? ? 1.0 : 0.0)
265
+ Blog::Models.create_schema :assume => (Blog::Models::Post.table_exists? ? 1.0 : 0.0)
270
266
  end
271
267
 
268
+ __END__
269
+ * {
270
+ margin: 0;
271
+ padding: 0;
272
+ }
273
+
274
+ body {
275
+ font: normal 14px Arial, 'Bitstream Vera Sans', Helvetica, sans-serif;
276
+ line-height: 1.5;
277
+ }
278
+
279
+ h1, h2, h3, h4 {
280
+ font-family: Georgia, serif;
281
+ font-weight: normal;
282
+ }
283
+
284
+ h1 {
285
+ background-color: #EEE;
286
+ border-bottom: 5px solid #6F812D;
287
+ outline: 5px solid #9CB441;
288
+ font-weight: normal;
289
+ font-size: 3em;
290
+ padding: 0.5em 0;
291
+ text-align: center;
292
+ }
293
+
294
+ h2 {
295
+ margin-top: 1em;
296
+ font-size: 2em;
297
+ }
298
+
299
+ h1 a { color: #143D55; text-decoration: none }
300
+ h1 a:hover { color: #143D55; text-decoration: underline }
301
+ h2 a { color: #287AA9; text-decoration: none }
302
+ h2 a:hover { color: #287AA9; text-decoration: underline }
303
+
304
+ #wrapper {
305
+ margin: 3em auto;
306
+ width: 700px;
307
+ }
308
+
309
+ p {
310
+ margin-bottom: 1em;
311
+ }
312
+
313
+ p.info, p#footer {
314
+ color: #999;
315
+ margin-left: 1em;
316
+ }
317
+
318
+ p.info a, p#footer a {
319
+ color: #999;
320
+ }
321
+
322
+ p.info a:hover, p#footer a:hover {
323
+ text-decoration: none;
324
+ }
325
+
326
+ a {
327
+ color: #6F812D;
328
+ }
329
+
330
+ a:hover {
331
+ color: #9CB441;
332
+ }
333
+
334
+ hr {
335
+ border-width: 5px 0;
336
+ border-style: solid;
337
+ border-color: #9CB441;
338
+ border-bottom-color: #6F812D;
339
+ height: 0;
340
+ }
341
+
342
+ p#footer {
343
+ font-size: 0.9em;
344
+ margin: 0;
345
+ padding: 1em;
346
+ text-align: center;
347
+ }
348
+
349
+ label {
350
+ display: block;
351
+ width: 100%;
352
+ }
353
+
354
+ input, textarea {
355
+ padding: 5px;
356
+ margin-bottom: 1em;
357
+ margin-right: 490px;
358
+ width: 200px;
359
+ }
360
+
361
+ input.submit {
362
+ width: auto;
363
+ }
364
+
365
+ textarea {
366
+ font: normal 14px Arial, 'Bitstream Vera Sans', Helvetica, sans-serif;
367
+ height: 300px;
368
+ width: 400px;
369
+ }
370
+