halorgium-actionpack 3.0.pre

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 (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