halorgium-actionpack 3.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data/CHANGELOG +5179 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +409 -0
  4. data/lib/abstract_controller.rb +16 -0
  5. data/lib/abstract_controller/base.rb +158 -0
  6. data/lib/abstract_controller/callbacks.rb +113 -0
  7. data/lib/abstract_controller/exceptions.rb +12 -0
  8. data/lib/abstract_controller/helpers.rb +151 -0
  9. data/lib/abstract_controller/layouts.rb +250 -0
  10. data/lib/abstract_controller/localized_cache.rb +49 -0
  11. data/lib/abstract_controller/logger.rb +61 -0
  12. data/lib/abstract_controller/rendering_controller.rb +188 -0
  13. data/lib/action_controller.rb +72 -0
  14. data/lib/action_controller/base.rb +168 -0
  15. data/lib/action_controller/caching.rb +80 -0
  16. data/lib/action_controller/caching/actions.rb +163 -0
  17. data/lib/action_controller/caching/fragments.rb +116 -0
  18. data/lib/action_controller/caching/pages.rb +154 -0
  19. data/lib/action_controller/caching/sweeping.rb +97 -0
  20. data/lib/action_controller/deprecated.rb +4 -0
  21. data/lib/action_controller/deprecated/integration_test.rb +2 -0
  22. data/lib/action_controller/deprecated/performance_test.rb +1 -0
  23. data/lib/action_controller/dispatch/dispatcher.rb +57 -0
  24. data/lib/action_controller/metal.rb +129 -0
  25. data/lib/action_controller/metal/benchmarking.rb +73 -0
  26. data/lib/action_controller/metal/compatibility.rb +145 -0
  27. data/lib/action_controller/metal/conditional_get.rb +86 -0
  28. data/lib/action_controller/metal/configuration.rb +28 -0
  29. data/lib/action_controller/metal/cookies.rb +105 -0
  30. data/lib/action_controller/metal/exceptions.rb +55 -0
  31. data/lib/action_controller/metal/filter_parameter_logging.rb +77 -0
  32. data/lib/action_controller/metal/flash.rb +162 -0
  33. data/lib/action_controller/metal/head.rb +27 -0
  34. data/lib/action_controller/metal/helpers.rb +115 -0
  35. data/lib/action_controller/metal/hide_actions.rb +47 -0
  36. data/lib/action_controller/metal/http_authentication.rb +312 -0
  37. data/lib/action_controller/metal/layouts.rb +171 -0
  38. data/lib/action_controller/metal/mime_responds.rb +317 -0
  39. data/lib/action_controller/metal/rack_convenience.rb +27 -0
  40. data/lib/action_controller/metal/redirector.rb +22 -0
  41. data/lib/action_controller/metal/render_options.rb +103 -0
  42. data/lib/action_controller/metal/rendering_controller.rb +57 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +108 -0
  44. data/lib/action_controller/metal/rescuable.rb +13 -0
  45. data/lib/action_controller/metal/responder.rb +200 -0
  46. data/lib/action_controller/metal/session.rb +15 -0
  47. data/lib/action_controller/metal/session_management.rb +45 -0
  48. data/lib/action_controller/metal/streaming.rb +188 -0
  49. data/lib/action_controller/metal/testing.rb +39 -0
  50. data/lib/action_controller/metal/url_for.rb +41 -0
  51. data/lib/action_controller/metal/verification.rb +130 -0
  52. data/lib/action_controller/middleware.rb +38 -0
  53. data/lib/action_controller/notifications.rb +10 -0
  54. data/lib/action_controller/polymorphic_routes.rb +183 -0
  55. data/lib/action_controller/record_identifier.rb +91 -0
  56. data/lib/action_controller/testing/process.rb +111 -0
  57. data/lib/action_controller/testing/test_case.rb +345 -0
  58. data/lib/action_controller/translation.rb +13 -0
  59. data/lib/action_controller/url_rewriter.rb +204 -0
  60. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  61. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  62. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +176 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  65. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  66. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  67. data/lib/action_dispatch.rb +70 -0
  68. data/lib/action_dispatch/http/headers.rb +33 -0
  69. data/lib/action_dispatch/http/mime_type.rb +231 -0
  70. data/lib/action_dispatch/http/mime_types.rb +23 -0
  71. data/lib/action_dispatch/http/request.rb +539 -0
  72. data/lib/action_dispatch/http/response.rb +290 -0
  73. data/lib/action_dispatch/http/status_codes.rb +42 -0
  74. data/lib/action_dispatch/http/utils.rb +20 -0
  75. data/lib/action_dispatch/middleware/callbacks.rb +50 -0
  76. data/lib/action_dispatch/middleware/params_parser.rb +79 -0
  77. data/lib/action_dispatch/middleware/rescue.rb +26 -0
  78. data/lib/action_dispatch/middleware/session/abstract_store.rb +208 -0
  79. data/lib/action_dispatch/middleware/session/cookie_store.rb +235 -0
  80. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
  81. data/lib/action_dispatch/middleware/show_exceptions.rb +143 -0
  82. data/lib/action_dispatch/middleware/stack.rb +116 -0
  83. data/lib/action_dispatch/middleware/static.rb +44 -0
  84. data/lib/action_dispatch/middleware/string_coercion.rb +29 -0
  85. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +24 -0
  86. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +26 -0
  87. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
  88. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +29 -0
  89. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +2 -0
  90. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +10 -0
  91. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +21 -0
  92. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +2 -0
  93. data/lib/action_dispatch/routing.rb +381 -0
  94. data/lib/action_dispatch/routing/deprecated_mapper.rb +878 -0
  95. data/lib/action_dispatch/routing/mapper.rb +327 -0
  96. data/lib/action_dispatch/routing/route.rb +49 -0
  97. data/lib/action_dispatch/routing/route_set.rb +497 -0
  98. data/lib/action_dispatch/testing/assertions.rb +8 -0
  99. data/lib/action_dispatch/testing/assertions/dom.rb +35 -0
  100. data/lib/action_dispatch/testing/assertions/model.rb +19 -0
  101. data/lib/action_dispatch/testing/assertions/response.rb +145 -0
  102. data/lib/action_dispatch/testing/assertions/routing.rb +144 -0
  103. data/lib/action_dispatch/testing/assertions/selector.rb +639 -0
  104. data/lib/action_dispatch/testing/assertions/tag.rb +123 -0
  105. data/lib/action_dispatch/testing/integration.rb +504 -0
  106. data/lib/action_dispatch/testing/performance_test.rb +15 -0
  107. data/lib/action_dispatch/testing/test_request.rb +83 -0
  108. data/lib/action_dispatch/testing/test_response.rb +131 -0
  109. data/lib/action_pack.rb +24 -0
  110. data/lib/action_pack/version.rb +9 -0
  111. data/lib/action_view.rb +58 -0
  112. data/lib/action_view/base.rb +308 -0
  113. data/lib/action_view/context.rb +44 -0
  114. data/lib/action_view/erb/util.rb +48 -0
  115. data/lib/action_view/helpers.rb +62 -0
  116. data/lib/action_view/helpers/active_model_helper.rb +306 -0
  117. data/lib/action_view/helpers/ajax_helper.rb +68 -0
  118. data/lib/action_view/helpers/asset_tag_helper.rb +830 -0
  119. data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
  120. data/lib/action_view/helpers/cache_helper.rb +39 -0
  121. data/lib/action_view/helpers/capture_helper.rb +168 -0
  122. data/lib/action_view/helpers/date_helper.rb +988 -0
  123. data/lib/action_view/helpers/debug_helper.rb +38 -0
  124. data/lib/action_view/helpers/form_helper.rb +1102 -0
  125. data/lib/action_view/helpers/form_options_helper.rb +600 -0
  126. data/lib/action_view/helpers/form_tag_helper.rb +495 -0
  127. data/lib/action_view/helpers/javascript_helper.rb +208 -0
  128. data/lib/action_view/helpers/number_helper.rb +311 -0
  129. data/lib/action_view/helpers/prototype_helper.rb +1309 -0
  130. data/lib/action_view/helpers/raw_output_helper.rb +9 -0
  131. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  132. data/lib/action_view/helpers/record_tag_helper.rb +58 -0
  133. data/lib/action_view/helpers/sanitize_helper.rb +259 -0
  134. data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
  135. data/lib/action_view/helpers/tag_helper.rb +151 -0
  136. data/lib/action_view/helpers/text_helper.rb +594 -0
  137. data/lib/action_view/helpers/translation_helper.rb +39 -0
  138. data/lib/action_view/helpers/url_helper.rb +639 -0
  139. data/lib/action_view/locale/en.yml +117 -0
  140. data/lib/action_view/paths.rb +80 -0
  141. data/lib/action_view/render/partials.rb +342 -0
  142. data/lib/action_view/render/rendering.rb +134 -0
  143. data/lib/action_view/safe_buffer.rb +28 -0
  144. data/lib/action_view/template/error.rb +101 -0
  145. data/lib/action_view/template/handler.rb +36 -0
  146. data/lib/action_view/template/handlers.rb +52 -0
  147. data/lib/action_view/template/handlers/builder.rb +17 -0
  148. data/lib/action_view/template/handlers/erb.rb +53 -0
  149. data/lib/action_view/template/handlers/rjs.rb +18 -0
  150. data/lib/action_view/template/resolver.rb +165 -0
  151. data/lib/action_view/template/template.rb +131 -0
  152. data/lib/action_view/template/text.rb +38 -0
  153. data/lib/action_view/test_case.rb +163 -0
  154. metadata +236 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2004-2009 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,409 @@
1
+ = Action Pack -- On rails from request to response
2
+
3
+ Action Pack splits the response to a web request into a controller part
4
+ (performing the logic) and a view part (rendering a template). This two-step
5
+ approach is known as an action, which will normally create, read, update, or
6
+ delete (CRUD for short) some sort of model part (often backed by a database)
7
+ before choosing either to render a template or redirecting to another action.
8
+
9
+ Action Pack implements these actions as public methods on Action Controllers
10
+ and uses Action Views to implement the template rendering. Action Controllers
11
+ are then responsible for handling all the actions relating to a certain part
12
+ of an application. This grouping usually consists of actions for lists and for
13
+ CRUDs revolving around a single (or a few) model objects. So ContactsController
14
+ would be responsible for listing contacts, creating, deleting, and updating
15
+ contacts. A WeblogController could be responsible for both posts and comments.
16
+
17
+ Action View templates are written using embedded Ruby in tags mingled in with
18
+ the HTML. To avoid cluttering the templates with code, a bunch of helper
19
+ classes provide common behavior for forms, dates, and strings. And it's easy
20
+ to add specific helpers to keep the separation as the application evolves.
21
+
22
+ Note: Some of the features, such as scaffolding and form building, are tied to
23
+ ActiveRecord[http://activerecord.rubyonrails.org] (an object-relational
24
+ mapping package), but that doesn't mean that Action Pack depends on Active
25
+ Record. Action Pack is an independent package that can be used with any sort
26
+ of backend (Instiki[http://www.instiki.org], which is based on an older version
27
+ of Action Pack, used Madeleine for example). Read more about the role Action
28
+ Pack can play when used together with Active Record on
29
+ http://www.rubyonrails.org.
30
+
31
+ A short rundown of the major features:
32
+
33
+ * Actions grouped in controller as methods instead of separate command objects
34
+ and can therefore share helper methods
35
+
36
+ CustomersController < ActionController::Base
37
+ def show
38
+ @customer = find_customer
39
+ end
40
+
41
+ def update
42
+ @customer = find_customer
43
+ @customer.attributes = params[:customer]
44
+ @customer.save ?
45
+ redirect_to(:action => "show") :
46
+ render(:action => "edit")
47
+ end
48
+
49
+ private
50
+ def find_customer() Customer.find(params[:id]) end
51
+ end
52
+
53
+ {Learn more}[link:classes/ActionController/Base.html]
54
+
55
+
56
+ * Embedded Ruby for templates (no new "easy" template language)
57
+
58
+ <% for post in @posts %>
59
+ Title: <%= post.title %>
60
+ <% end %>
61
+
62
+ All post titles: <%= @posts.collect{ |p| p.title }.join ", " %>
63
+
64
+ <% unless @person.is_client? %>
65
+ Not for clients to see...
66
+ <% end %>
67
+
68
+ {Learn more}[link:classes/ActionView.html]
69
+
70
+
71
+ * Builder-based templates (great for XML content, like RSS)
72
+
73
+ xml.rss("version" => "2.0") do
74
+ xml.channel do
75
+ xml.title(@feed_title)
76
+ xml.link(@url)
77
+ xml.description "Basecamp: Recent items"
78
+ xml.language "en-us"
79
+ xml.ttl "40"
80
+
81
+ for item in @recent_items
82
+ xml.item do
83
+ xml.title(item_title(item))
84
+ xml.description(item_description(item))
85
+ xml.pubDate(item_pubDate(item))
86
+ xml.guid(@recent_items.url(item))
87
+ xml.link(@recent_items.url(item))
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ {Learn more}[link:classes/ActionView/Base.html]
94
+
95
+
96
+ * Filters for pre and post processing of the response (as methods, procs, and classes)
97
+
98
+ class WeblogController < ActionController::Base
99
+ before_filter :authenticate, :cache, :audit
100
+ after_filter { |c| c.response.body = Gzip::compress(c.response.body) }
101
+ after_filter LocalizeFilter
102
+
103
+ def index
104
+ # Before this action is run, the user will be authenticated, the cache
105
+ # will be examined to see if a valid copy of the results already
106
+ # exists, and the action will be logged for auditing.
107
+
108
+ # After this action has run, the output will first be localized then
109
+ # compressed to minimize bandwidth usage
110
+ end
111
+
112
+ private
113
+ def authenticate
114
+ # Implement the filter with full access to both request and response
115
+ end
116
+ end
117
+
118
+ {Learn more}[link:classes/ActionController/Filters/ClassMethods.html]
119
+
120
+
121
+ * Helpers for forms, dates, action links, and text
122
+
123
+ <%= text_field "post", "title", "size" => 30 %>
124
+ <%= html_date_select(Date.today) %>
125
+ <%= link_to "New post", :controller => "post", :action => "new" %>
126
+ <%= truncate(post.title, :length => 25) %>
127
+
128
+ {Learn more}[link:classes/ActionView/Helpers.html]
129
+
130
+
131
+ * Layout sharing for template reuse (think simple version of Struts
132
+ Tiles[http://jakarta.apache.org/struts/userGuide/dev_tiles.html])
133
+
134
+ class WeblogController < ActionController::Base
135
+ layout "weblog_layout"
136
+
137
+ def hello_world
138
+ end
139
+ end
140
+
141
+ Layout file (called weblog_layout):
142
+ <html><body><%= yield %></body></html>
143
+
144
+ Template for hello_world action:
145
+ <h1>Hello world</h1>
146
+
147
+ Result of running hello_world action:
148
+ <html><body><h1>Hello world</h1></body></html>
149
+
150
+ {Learn more}[link:classes/ActionController/Layout/ClassMethods.html]
151
+
152
+
153
+ * Routing makes pretty urls incredibly easy
154
+
155
+ map.connect 'clients/:client_name/:project_name/:controller/:action'
156
+
157
+ Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with
158
+ { "client_name" => "37signals", "project_name" => "basecamp" } in params[:params]
159
+
160
+ From that URL, you can rewrite the redirect in a number of ways:
161
+
162
+ redirect_to(:action => "edit") =>
163
+ /clients/37signals/basecamp/project/dash
164
+
165
+ redirect_to(:client_name => "nextangle", :project_name => "rails") =>
166
+ /clients/nextangle/rails/project/dash
167
+
168
+ {Learn more}[link:classes/ActionController/Base.html]
169
+
170
+
171
+ * Javascript and Ajax integration
172
+
173
+ link_to_function "Greeting", "alert('Hello world!')"
174
+ link_to_remote "Delete this post", :update => "posts",
175
+ :url => { :action => "destroy", :id => post.id }
176
+
177
+ {Learn more}[link:classes/ActionView/Helpers/JavaScriptHelper.html]
178
+
179
+
180
+ * Easy testing of both controller and rendered template through ActionController::TestCase
181
+
182
+ class LoginControllerTest < ActionController::TestCase
183
+ def test_failing_authenticate
184
+ process :authenticate, :user_name => "nop", :password => ""
185
+ assert flash.has_key?(:alert)
186
+ assert_redirected_to :action => "index"
187
+ end
188
+ end
189
+
190
+ {Learn more}[link:classes/ActionController/TestCase.html]
191
+
192
+
193
+ * Automated benchmarking and integrated logging
194
+
195
+ Processing WeblogController#index (for 127.0.0.1 at Fri May 28 00:41:55)
196
+ Parameters: {"action"=>"index", "controller"=>"weblog"}
197
+ Rendering weblog/index (200 OK)
198
+ Completed in 0.029281 (34 reqs/sec)
199
+
200
+ If Active Record is used as the model, you'll have the database debugging
201
+ as well:
202
+
203
+ Processing PostsController#create (for 127.0.0.1 at Sat Jun 19 14:04:23)
204
+ Params: {"controller"=>"posts", "action"=>"create",
205
+ "post"=>{"title"=>"this is good"} }
206
+ SQL (0.000627) INSERT INTO posts (title) VALUES('this is good')
207
+ Redirected to http://example.com/posts/5
208
+ Completed in 0.221764 (4 reqs/sec) | DB: 0.059920 (27%)
209
+
210
+ You specify a logger through a class method, such as:
211
+
212
+ ActionController::Base.logger = Logger.new("Application Log")
213
+ ActionController::Base.logger = Log4r::Logger.new("Application Log")
214
+
215
+
216
+ * Caching at three levels of granularity (page, action, fragment)
217
+
218
+ class WeblogController < ActionController::Base
219
+ caches_page :show
220
+ caches_action :account
221
+
222
+ def show
223
+ # the output of the method will be cached as
224
+ # ActionController::Base.page_cache_directory + "/weblog/show/n.html"
225
+ # and the web server will pick it up without even hitting Rails
226
+ end
227
+
228
+ def account
229
+ # the output of the method will be cached in the fragment store
230
+ # but Rails is hit to retrieve it, so filters are run
231
+ end
232
+
233
+ def update
234
+ List.update(params[:list][:id], params[:list])
235
+ expire_page :action => "show", :id => params[:list][:id]
236
+ expire_action :action => "account"
237
+ redirect_to :action => "show", :id => params[:list][:id]
238
+ end
239
+ end
240
+
241
+ {Learn more}[link:classes/ActionController/Caching.html]
242
+
243
+
244
+ * Powerful debugging mechanism for local requests
245
+
246
+ All exceptions raised on actions performed on the request of a local user
247
+ will be presented with a tailored debugging screen that includes exception
248
+ message, stack trace, request parameters, session contents, and the
249
+ half-finished response.
250
+
251
+ {Learn more}[link:classes/ActionController/Rescue.html]
252
+
253
+
254
+ * Scaffolding for Active Record model objects
255
+
256
+ class AccountController < ActionController::Base
257
+ scaffold :account
258
+ end
259
+
260
+ The AccountController now has the full CRUD range of actions and default
261
+ templates: list, show, destroy, new, create, edit, update
262
+
263
+ {Learn more}[link:classes/ActionController/Scaffolding/ClassMethods.html]
264
+
265
+
266
+ * Form building for Active Record model objects
267
+
268
+ The post object has a title (varchar), content (text), and
269
+ written_on (date)
270
+
271
+ <%= form "post" %>
272
+
273
+ ...will generate something like (the selects will have more options, of
274
+ course):
275
+
276
+ <form action="create" method="POST">
277
+ <p>
278
+ <b>Title:</b><br/>
279
+ <input type="text" name="post[title]" value="<%= @post.title %>" />
280
+ </p>
281
+ <p>
282
+ <b>Content:</b><br/>
283
+ <textarea name="post[content]"><%= @post.title %></textarea>
284
+ </p>
285
+ <p>
286
+ <b>Written on:</b><br/>
287
+ <select name='post[written_on(3i)]'><option>18</option></select>
288
+ <select name='post[written_on(2i)]'><option value='7'>July</option></select>
289
+ <select name='post[written_on(1i)]'><option>2004</option></select>
290
+ </p>
291
+
292
+ <input type="submit" value="Create">
293
+ </form>
294
+
295
+ This form generates a params[:post] array that can be used directly in a save action:
296
+
297
+ class WeblogController < ActionController::Base
298
+ def create
299
+ post = Post.create(params[:post])
300
+ redirect_to :action => "show", :id => post.id
301
+ end
302
+ end
303
+
304
+ {Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html]
305
+
306
+
307
+ * Runs on top of WEBrick, Mongrel, CGI, FCGI, and mod_ruby
308
+
309
+
310
+ == Simple example (from outside of Rails)
311
+
312
+ This example will implement a simple weblog system using inline templates and
313
+ an Active Record model. So let's build that WeblogController with just a few
314
+ methods:
315
+
316
+ require 'action_controller'
317
+ require 'post'
318
+
319
+ class WeblogController < ActionController::Base
320
+ layout "weblog/layout"
321
+
322
+ def index
323
+ @posts = Post.find(:all)
324
+ end
325
+
326
+ def show
327
+ @post = Post.find(params[:id])
328
+ end
329
+
330
+ def new
331
+ @post = Post.new
332
+ end
333
+
334
+ def create
335
+ @post = Post.create(params[:post])
336
+ redirect_to :action => "show", :id => @post.id
337
+ end
338
+ end
339
+
340
+ WeblogController::Base.view_paths = [ File.dirname(__FILE__) ]
341
+ WeblogController.process_cgi if $0 == __FILE__
342
+
343
+ The last two lines are responsible for telling ActionController where the
344
+ template files are located and actually running the controller on a new
345
+ request from the web-server (like to be Apache).
346
+
347
+ And the templates look like this:
348
+
349
+ weblog/layout.html.erb:
350
+ <html><body>
351
+ <%= yield %>
352
+ </body></html>
353
+
354
+ weblog/index.html.erb:
355
+ <% for post in @posts %>
356
+ <p><%= link_to(post.title, :action => "show", :id => post.id) %></p>
357
+ <% end %>
358
+
359
+ weblog/show.html.erb:
360
+ <p>
361
+ <b><%= @post.title %></b><br/>
362
+ <b><%= @post.content %></b>
363
+ </p>
364
+
365
+ weblog/new.html.erb:
366
+ <%= form "post" %>
367
+
368
+ This simple setup will list all the posts in the system on the index page,
369
+ which is called by accessing /weblog/. It uses the form builder for the Active
370
+ Record model to make the new screen, which in turn hands everything over to
371
+ the create action (that's the default target for the form builder when given a
372
+ new model). After creating the post, it'll redirect to the show page using
373
+ an URL such as /weblog/5 (where 5 is the id of the post).
374
+
375
+
376
+ == Download
377
+
378
+ The latest version of Action Pack can be found at
379
+
380
+ * http://rubyforge.org/project/showfiles.php?group_id=249
381
+
382
+ Documentation can be found at
383
+
384
+ * http://api.rubyonrails.com
385
+
386
+
387
+ == Installation
388
+
389
+ You can install Action Pack with the following command.
390
+
391
+ % [sudo] ruby install.rb
392
+
393
+ from its distribution directory.
394
+
395
+
396
+ == License
397
+
398
+ Action Pack is released under the MIT license.
399
+
400
+
401
+ == Support
402
+
403
+ The Action Pack homepage is http://www.rubyonrails.org. You can find
404
+ the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack.
405
+ And as Jim from Rake says:
406
+
407
+ Feel free to submit commits or feature requests. If you send a patch,
408
+ remember to update the corresponding unit tests. If fact, I prefer
409
+ new feature to be submitted in the form of new unit tests.
@@ -0,0 +1,16 @@
1
+ require "active_support/core_ext/module/attr_internal"
2
+ require "active_support/core_ext/module/delegation"
3
+
4
+ module AbstractController
5
+ autoload :Base, "abstract_controller/base"
6
+ autoload :Callbacks, "abstract_controller/callbacks"
7
+ autoload :Helpers, "abstract_controller/helpers"
8
+ autoload :Layouts, "abstract_controller/layouts"
9
+ autoload :LocalizedCache, "abstract_controller/localized_cache"
10
+ autoload :Logger, "abstract_controller/logger"
11
+ autoload :RenderingController, "abstract_controller/rendering_controller"
12
+ # === Exceptions
13
+ autoload :ActionNotFound, "abstract_controller/exceptions"
14
+ autoload :DoubleRenderError, "abstract_controller/exceptions"
15
+ autoload :Error, "abstract_controller/exceptions"
16
+ end
@@ -0,0 +1,158 @@
1
+ module AbstractController
2
+
3
+ class Base
4
+ attr_internal :response_body
5
+ attr_internal :action_name
6
+
7
+ class << self
8
+ attr_reader :abstract
9
+ alias_method :abstract?, :abstract
10
+
11
+ # Define a controller as abstract. See internal_methods for more
12
+ # details.
13
+ def abstract!
14
+ @abstract = true
15
+ end
16
+
17
+ def inherited(klass)
18
+ ::AbstractController::Base.descendants << klass.to_s
19
+ super
20
+ end
21
+
22
+ # A list of all descendents of AbstractController::Base. This is
23
+ # useful for initializers which need to add behavior to all controllers.
24
+ def descendants
25
+ @descendants ||= []
26
+ end
27
+
28
+ # A list of all internal methods for a controller. This finds the first
29
+ # abstract superclass of a controller, and gets a list of all public
30
+ # instance methods on that abstract class. Public instance methods of
31
+ # a controller would normally be considered action methods, so we
32
+ # are removing those methods on classes declared as abstract
33
+ # (ActionController::Metal and ActionController::Base are defined
34
+ # as abstract)
35
+ def internal_methods
36
+ controller = self
37
+ controller = controller.superclass until controller.abstract?
38
+ controller.public_instance_methods(true)
39
+ end
40
+
41
+ # The list of hidden actions to an empty Array. Defaults to an
42
+ # empty Array. This can be modified by other modules or subclasses
43
+ # to specify particular actions as hidden.
44
+ #
45
+ # ==== Returns
46
+ # Array[String]:: An array of method names that should not be
47
+ # considered actions.
48
+ def hidden_actions
49
+ []
50
+ end
51
+
52
+ # A list of method names that should be considered actions. This
53
+ # includes all public instance methods on a controller, less
54
+ # any internal methods (see #internal_methods), adding back in
55
+ # any methods that are internal, but still exist on the class
56
+ # itself. Finally, #hidden_actions are removed.
57
+ #
58
+ # ==== Returns
59
+ # Array[String]:: A list of all methods that should be considered
60
+ # actions.
61
+ def action_methods
62
+ @action_methods ||=
63
+ # All public instance methods of this class, including ancestors
64
+ public_instance_methods(true).map { |m| m.to_s }.to_set -
65
+ # Except for public instance methods of Base and its ancestors
66
+ internal_methods.map { |m| m.to_s } +
67
+ # Be sure to include shadowed public instance methods of this class
68
+ public_instance_methods(false).map { |m| m.to_s } -
69
+ # And always exclude explicitly hidden actions
70
+ hidden_actions
71
+ end
72
+ end
73
+
74
+ abstract!
75
+
76
+ # Calls the action going through the entire action dispatch stack.
77
+ #
78
+ # The actual method that is called is determined by calling
79
+ # #method_for_action. If no method can handle the action, then an
80
+ # ActionNotFound error is raised.
81
+ #
82
+ # ==== Returns
83
+ # self
84
+ def process(action)
85
+ @_action_name = action_name = action.to_s
86
+
87
+ unless action_name = method_for_action(action_name)
88
+ raise ActionNotFound, "The action '#{action}' could not be found"
89
+ end
90
+
91
+ process_action(action_name)
92
+ end
93
+
94
+ private
95
+ # Returns true if the name can be considered an action. This can
96
+ # be overridden in subclasses to modify the semantics of what
97
+ # can be considered an action.
98
+ #
99
+ # ==== Parameters
100
+ # name<String>:: The name of an action to be tested
101
+ #
102
+ # ==== Returns
103
+ # TrueClass, FalseClass
104
+ def action_method?(name)
105
+ self.class.action_methods.include?(name)
106
+ end
107
+
108
+ # Call the action. Override this in a subclass to modify the
109
+ # behavior around processing an action. This, and not #process,
110
+ # is the intended way to override action dispatching.
111
+ def process_action(method_name)
112
+ send_action(method_name)
113
+ end
114
+
115
+ # Actually call the method associated with the action. Override
116
+ # this method if you wish to change how action methods are called,
117
+ # not to add additional behavior around it. For example, you would
118
+ # override #send_action if you want to inject arguments into the
119
+ # method.
120
+ alias send_action send
121
+
122
+ # If the action name was not found, but a method called "action_missing"
123
+ # was found, #method_for_action will return "_handle_action_missing".
124
+ # This method calls #action_missing with the current action name.
125
+ def _handle_action_missing
126
+ action_missing(@_action_name)
127
+ end
128
+
129
+ # Takes an action name and returns the name of the method that will
130
+ # handle the action. In normal cases, this method returns the same
131
+ # name as it receives. By default, if #method_for_action receives
132
+ # a name that is not an action, it will look for an #action_missing
133
+ # method and return "_handle_action_missing" if one is found.
134
+ #
135
+ # Subclasses may override this method to add additional conditions
136
+ # that should be considered an action. For instance, an HTTP controller
137
+ # with a template matching the action name is considered to exist.
138
+ #
139
+ # If you override this method to handle additional cases, you may
140
+ # also provide a method (like _handle_method_missing) to handle
141
+ # the case.
142
+ #
143
+ # If none of these conditions are true, and method_for_action
144
+ # returns nil, an ActionNotFound exception will be raised.
145
+ #
146
+ # ==== Parameters
147
+ # action_name<String>:: An action name to find a method name for
148
+ #
149
+ # ==== Returns
150
+ # String:: The name of the method that handles the action
151
+ # nil:: No method name could be found. Raise ActionNotFound.
152
+ def method_for_action(action_name)
153
+ if action_method?(action_name) then action_name
154
+ elsif respond_to?(:action_missing, true) then "_handle_action_missing"
155
+ end
156
+ end
157
+ end
158
+ end