rails 2.3.2 → 2.3.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails might be problematic. Click here for more details.

Files changed (118) hide show
  1. data/CHANGELOG +4 -0
  2. data/Rakefile +11 -9
  3. data/configs/routes.rb +1 -1
  4. data/guides/files/javascripts/code_highlighter.js +188 -0
  5. data/guides/files/javascripts/guides.js +8 -0
  6. data/guides/files/javascripts/highlighters.js +90 -0
  7. data/guides/files/stylesheets/main.css +441 -0
  8. data/guides/files/stylesheets/print.css +52 -0
  9. data/guides/files/stylesheets/reset.css +43 -0
  10. data/guides/files/stylesheets/style.css +13 -0
  11. data/guides/files/stylesheets/syntax.css +31 -0
  12. data/guides/images/belongs_to.png +0 -0
  13. data/guides/images/book_icon.gif +0 -0
  14. data/guides/images/bullet.gif +0 -0
  15. data/guides/images/chapters_icon.gif +0 -0
  16. data/guides/images/check_bullet.gif +0 -0
  17. data/guides/images/credits_pic_blank.gif +0 -0
  18. data/guides/images/csrf.png +0 -0
  19. data/guides/images/customized_error_messages.png +0 -0
  20. data/guides/images/error_messages.png +0 -0
  21. data/guides/images/feature_tile.gif +0 -0
  22. data/guides/images/footer_tile.gif +0 -0
  23. data/guides/images/fxn.jpg +0 -0
  24. data/guides/images/grey_bullet.gif +0 -0
  25. data/guides/images/habtm.png +0 -0
  26. data/guides/images/has_many.png +0 -0
  27. data/guides/images/has_many_through.png +0 -0
  28. data/guides/images/has_one.png +0 -0
  29. data/guides/images/has_one_through.png +0 -0
  30. data/guides/images/header_backdrop.png +0 -0
  31. data/guides/images/header_tile.gif +0 -0
  32. data/guides/images/i18n/demo_localized_pirate.png +0 -0
  33. data/guides/images/i18n/demo_translated_en.png +0 -0
  34. data/guides/images/i18n/demo_translated_pirate.png +0 -0
  35. data/guides/images/i18n/demo_translation_missing.png +0 -0
  36. data/guides/images/i18n/demo_untranslated.png +0 -0
  37. data/guides/images/icons/README +5 -0
  38. data/guides/images/icons/callouts/1.png +0 -0
  39. data/guides/images/icons/callouts/10.png +0 -0
  40. data/guides/images/icons/callouts/11.png +0 -0
  41. data/guides/images/icons/callouts/12.png +0 -0
  42. data/guides/images/icons/callouts/13.png +0 -0
  43. data/guides/images/icons/callouts/14.png +0 -0
  44. data/guides/images/icons/callouts/15.png +0 -0
  45. data/guides/images/icons/callouts/2.png +0 -0
  46. data/guides/images/icons/callouts/3.png +0 -0
  47. data/guides/images/icons/callouts/4.png +0 -0
  48. data/guides/images/icons/callouts/5.png +0 -0
  49. data/guides/images/icons/callouts/6.png +0 -0
  50. data/guides/images/icons/callouts/7.png +0 -0
  51. data/guides/images/icons/callouts/8.png +0 -0
  52. data/guides/images/icons/callouts/9.png +0 -0
  53. data/guides/images/icons/caution.png +0 -0
  54. data/guides/images/icons/example.png +0 -0
  55. data/guides/images/icons/home.png +0 -0
  56. data/guides/images/icons/important.png +0 -0
  57. data/guides/images/icons/next.png +0 -0
  58. data/guides/images/icons/note.png +0 -0
  59. data/guides/images/icons/prev.png +0 -0
  60. data/guides/images/icons/tip.png +0 -0
  61. data/guides/images/icons/up.png +0 -0
  62. data/guides/images/icons/warning.png +0 -0
  63. data/guides/images/nav_arrow.gif +0 -0
  64. data/guides/images/polymorphic.png +0 -0
  65. data/guides/images/posts_index.png +0 -0
  66. data/guides/images/rails_guides_logo.gif +0 -0
  67. data/guides/images/rails_logo_remix.gif +0 -0
  68. data/guides/images/rails_welcome.png +0 -0
  69. data/guides/images/session_fixation.png +0 -0
  70. data/guides/images/tab_grey.gif +0 -0
  71. data/guides/images/tab_info.gif +0 -0
  72. data/guides/images/tab_note.gif +0 -0
  73. data/guides/images/tab_red.gif +0 -0
  74. data/guides/images/tab_yellow.gif +0 -0
  75. data/guides/images/tab_yellow.png +0 -0
  76. data/guides/images/validation_error_messages.png +0 -0
  77. data/guides/rails_guides.rb +42 -0
  78. data/guides/rails_guides/generator.rb +138 -0
  79. data/guides/rails_guides/helpers.rb +34 -0
  80. data/guides/rails_guides/indexer.rb +55 -0
  81. data/guides/rails_guides/textile_extensions.rb +41 -0
  82. data/guides/source/2_2_release_notes.textile +422 -0
  83. data/guides/source/2_3_release_notes.textile +610 -0
  84. data/guides/source/action_controller_overview.textile +776 -0
  85. data/guides/source/action_mailer_basics.textile +424 -0
  86. data/guides/source/active_record_basics.textile +135 -0
  87. data/guides/source/active_record_querying.textile +969 -0
  88. data/guides/source/activerecord_validations_callbacks.textile +1086 -0
  89. data/guides/source/association_basics.textile +1781 -0
  90. data/guides/source/caching_with_rails.textile +524 -0
  91. data/guides/source/command_line.textile +589 -0
  92. data/guides/source/configuring.textile +234 -0
  93. data/guides/source/contribute.textile +71 -0
  94. data/guides/source/contributing_to_rails.textile +239 -0
  95. data/guides/source/credits.erb.textile +52 -0
  96. data/guides/source/debugging_rails_applications.textile +709 -0
  97. data/guides/source/form_helpers.textile +766 -0
  98. data/guides/source/getting_started.textile +1297 -0
  99. data/guides/source/i18n.textile +912 -0
  100. data/guides/source/index.erb.textile +124 -0
  101. data/guides/source/layout.html.erb +103 -0
  102. data/guides/source/layouts_and_rendering.textile +979 -0
  103. data/guides/source/migrations.textile +591 -0
  104. data/guides/source/nested_model_forms.textile +222 -0
  105. data/guides/source/performance_testing.textile +531 -0
  106. data/guides/source/plugins.textile +1512 -0
  107. data/guides/source/rails_on_rack.textile +309 -0
  108. data/guides/source/routing.textile +903 -0
  109. data/guides/source/security.textile +986 -0
  110. data/guides/source/testing.textile +951 -0
  111. data/lib/commands/performance/profiler.rb +1 -1
  112. data/lib/initializer.rb +27 -4
  113. data/lib/rails/gem_dependency.rb +35 -6
  114. data/lib/rails/rack/metal.rb +1 -1
  115. data/lib/rails/version.rb +1 -1
  116. data/lib/tasks/gems.rake +19 -6
  117. data/lib/test_help.rb +4 -1
  118. metadata +123 -7
@@ -0,0 +1,309 @@
1
+ h2. Rails on Rack
2
+
3
+ This guide covers Rails integration with Rack and interfacing with other Rack components. By referring to this guide, you will be able to:
4
+
5
+ * Create Rails Metal applications
6
+ * Use Rack Middlewares in your Rails applications
7
+ * Understand Action Pack's internal Middleware stack
8
+ * Define a custom Middleware stack
9
+
10
+ endprologue.
11
+
12
+ WARNING: This guide assumes a working knowledge of Rack protocol and Rack concepts such as middlewares, url maps and Rack::Builder.
13
+
14
+ h3. Introduction to Rack
15
+
16
+ bq. Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.
17
+
18
+ - "Rack API Documentation":http://rack.rubyforge.org/doc/
19
+
20
+ Explaining Rack is not really in the scope of this guide. In case you are not familiar with Rack's basics, you should check out the following links:
21
+
22
+ * "Official Rack Website":http://rack.github.com
23
+ * "Introducing Rack":http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html
24
+ * "Ruby on Rack #1 - Hello Rack!":http://m.onkey.org/2008/11/17/ruby-on-rack-1
25
+ * "Ruby on Rack #2 - The Builder":http://m.onkey.org/2008/11/18/ruby-on-rack-2-rack-builder
26
+
27
+ h3. Rails on Rack
28
+
29
+ h4. Rails Application's Rack Object
30
+
31
+ <tt>ActionController::Dispatcher.new</tt> is the primary Rack application object of a Rails application. Any Rack compliant web server should be using +ActionController::Dispatcher.new+ object to serve a Rails application.</p>
32
+
33
+ h4. +script/server+
34
+
35
+ <tt>script/server</tt> does the basic job of creating a +Rack::Builder+ object and starting the webserver. This is Rails' equivalent of Rack's +rackup+ script.
36
+
37
+ Here's how +script/server+ creates an instance of +Rack::Builder+
38
+
39
+ <ruby>
40
+ app = Rack::Builder.new {
41
+ use Rails::Rack::LogTailer unless options[:detach]
42
+ use Rails::Rack::Debugger if options[:debugger]
43
+
44
+ map "/" do
45
+ use Rails::Rack::Static
46
+ run ActionController::Dispatcher.new
47
+ end
48
+ }.to_app
49
+ </ruby>
50
+
51
+ Middlewares used in the code above are primarily useful only in the development envrionment. The following table explains their usage:
52
+
53
+ |_.Middleware|_.Purpose|
54
+ |Rails::Rack::LogTailer|Appends log file output to console|
55
+ |Rails::Rack::Static|Serves static files inside +RAILS_ROOT/public+ directory|
56
+ |Rails::Rack::Debugger|Starts Debugger|
57
+
58
+ h4. +rackup+
59
+
60
+ To use +rackup+ instead of Rails' +script/server+, you can put the following inside +config.ru+ of your Rails application's root directory:
61
+
62
+ <ruby>
63
+ # RAILS_ROOT/config.ru
64
+ require "config/environment"
65
+
66
+ use Rails::Rack::LogTailer
67
+ use Rails::Rack::Static
68
+ run ActionController::Dispatcher.new
69
+ </ruby>
70
+
71
+ And start the server:
72
+
73
+ <shell>
74
+ [lifo@null application]$ rackup
75
+ </shell>
76
+
77
+ To find out more about different +rackup+ options:
78
+
79
+ <shell>
80
+ [lifo@null application]$ rackup --help
81
+ </shell>
82
+
83
+ h3. Action Controller Middleware Stack
84
+
85
+ Many of Action Controller's internal components are implemented as Rack middlewares. +ActionController::Dispatcher+ uses +ActionController::MiddlewareStack+ to combine various internal and external middlewares to form a complete Rails Rack application.
86
+
87
+ NOTE: +ActionController::MiddlewareStack+ is Rails' equivalent of +Rack::Builder+, but built for better flexibility and more features to meet Rails' requirements.
88
+
89
+ h4. Inspecting Middleware Stack
90
+
91
+ Rails has a handy rake task for inspecting the middleware stack in use:
92
+
93
+ <shell>
94
+ $ rake middleware
95
+ </shell>
96
+
97
+ For a freshly generated Rails application, this might produce something like:
98
+
99
+ <ruby>
100
+ use Rack::Lock
101
+ use ActionController::Failsafe
102
+ use ActionController::Session::CookieStore, , {:secret=>"<secret>", :session_key=>"_<app>_session"}
103
+ use Rails::Rack::Metal
104
+ use ActionController::RewindableInput
105
+ use ActionController::ParamsParser
106
+ use Rack::MethodOverride
107
+ use Rack::Head
108
+ use ActiveRecord::QueryCache
109
+ run ActionController::Dispatcher.new
110
+ </ruby>
111
+
112
+ Purpose of each of this middlewares is explained in "Internal Middlewares":#internal-middleware-stack section.
113
+
114
+ h4. Configuring Middleware Stack
115
+
116
+ Rails provides a simple configuration interface +config.middleware+ for adding, removing and modifying the middlewares in the middleware stack via +environment.rb+ or the environment specific configuration file <tt>environments/&lt;environment&gt;.rb</tt>.
117
+
118
+ h5. Adding a Middleware
119
+
120
+ You can add a new middleware to the middleware stack using any of the following methods:
121
+
122
+ * +config.middleware.use(new_middleware, args)+ - Adds the new middleware at the bottom of the middleware stack.
123
+
124
+ * +config.middleware.insert_before(existing_middleware, new_middleware, args)+ - Adds the new middleware before the specified existing middleware in the middleware stack.
125
+
126
+ * +config.middleware.insert_after(existing_middleware, new_middleware, args)+ - Adds the new middleware after the specified existing middleware in the middleware stack.
127
+
128
+ <strong>Example:</strong>
129
+
130
+ <ruby>
131
+ # environment.rb
132
+
133
+ # Push Rack::BounceFavicon at the bottom
134
+ config.middleware.use Rack::BounceFavicon
135
+
136
+ # Add Lifo::Cache after ActiveRecord::QueryCache.
137
+ # Pass { :page_cache => false } argument to Lifo::Cache.
138
+ config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, :page_cache => false
139
+ </ruby>
140
+
141
+ h5. Swapping a Middleware
142
+
143
+ You can swap an existing middleware in the middleware stack using +config.middleware.swap+.
144
+
145
+ <strong>Example:</strong>
146
+
147
+ <ruby>
148
+ # environment.rb
149
+
150
+ # Replace ActionController::Failsafe with Lifo::Failsafe
151
+ config.middleware.swap ActionController::Failsafe, Lifo::Failsafe
152
+ </ruby>
153
+
154
+ h5. Middleware Stack is an Array
155
+
156
+ The middleware stack behaves just like a normal +Array+. You can use any +Array+ methods to insert, reorder, or remove items from the stack. Methods described in the section above are just convenience methods.
157
+
158
+ For example, the following removes the middleware matching the supplied class name:
159
+
160
+ <ruby>
161
+ config.middleware.delete(middleware)
162
+ </ruby>
163
+
164
+ h4. Internal Middleware Stack
165
+
166
+ Much of Action Controller's functionality is implemented as Middlewares. The following table explains the purpose of each of them:
167
+
168
+ |_.Middleware|_.Purpose|
169
+ |Rack::Lock|Sets +env["rack.multithread"]+ flag to +true+ and wraps the application within a Mutex.|
170
+ |ActionController::Failsafe|Returns HTTP Status +500+ to the client if an exception gets raised while dispatching.|
171
+ |ActiveRecord::QueryCache|Enable the Active Record query cache.|
172
+ |ActionController::Session::CookieStore|Uses the cookie based session store.|
173
+ |ActionController::Session::MemCacheStore|Uses the memcached based session store.|
174
+ |ActiveRecord::SessionStore|Uses the database based session store.|
175
+ |Rack::MethodOverride|Sets HTTP method based on +_method+ parameter or +env["HTTP_X_HTTP_METHOD_OVERRIDE"]+.|
176
+ |Rack::Head|Discards the response body if the client sends a +HEAD+ request.|
177
+
178
+ TIP: It's possible to use any of the above middlewares in your custom Rack stack.
179
+
180
+ h4. Customizing Internal Middleware Stack
181
+
182
+ It's possible to replace the entire middleware stack with a custom stack using +ActionController::Dispatcher.middleware=+.
183
+
184
+ <strong>Example:</strong>
185
+
186
+ Put the following in an initializer:
187
+
188
+ <ruby>
189
+ # config/initializers/stack.rb
190
+ ActionController::Dispatcher.middleware = ActionController::MiddlewareStack.new do |m|
191
+ m.use ActionController::Failsafe
192
+ m.use ActiveRecord::QueryCache
193
+ m.use Rack::Head
194
+ end
195
+ </ruby>
196
+
197
+ And now inspecting the middleware stack:
198
+
199
+ <shell>
200
+ $ rake middleware
201
+ (in /Users/lifo/Rails/blog)
202
+ use ActionController::Failsafe
203
+ use ActiveRecord::QueryCache
204
+ use Rack::Head
205
+ run ActionController::Dispatcher.new
206
+ </shell>
207
+
208
+ h4. Using Rack Builder
209
+
210
+ The following shows how to replace use +Rack::Builder+ instead of the Rails supplied +MiddlewareStack+.
211
+
212
+ <strong>Clear the existing Rails middleware stack</strong>
213
+
214
+ <ruby>
215
+ # environment.rb
216
+ config.middleware.clear
217
+ </ruby>
218
+
219
+ <br />
220
+ <strong>Add a +config.ru+ file to +RAILS_ROOT+</strong>
221
+
222
+ <ruby>
223
+ # config.ru
224
+ use MyOwnStackFromStratch
225
+ run ActionController::Dispatcher.new
226
+ </ruby>
227
+
228
+ h3. Rails Metal Applications
229
+
230
+ Rails Metal applications are minimal Rack applications specially designed for integrating with a typical Rails application. As Rails Metal Applications skip all of the Action Controller stack, serving a request has no overhead from the Rails framework itself. This is especially useful for infrequent cases where the performance of the full stack Rails framework is an issue.
231
+
232
+ Ryan Bates' railscast on the "Rails Metal":http://railscasts.com/episodes/150-rails-metal provides a nice walkthrough generating and using Rails Metal.
233
+
234
+ h4. Generating a Metal Application
235
+
236
+ Rails provides a generator called +metal+ for creating a new Metal application:
237
+
238
+ <shell>
239
+ $ script/generate metal poller
240
+ </shell>
241
+
242
+ This generates +poller.rb+ in the +app/metal+ directory:
243
+
244
+ <ruby>
245
+ # Allow the metal piece to run in isolation
246
+ require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
247
+
248
+ class Poller
249
+ def self.call(env)
250
+ if env["PATH_INFO"] =~ /^\/poller/
251
+ [200, {"Content-Type" => "text/html"}, ["Hello, World!"]]
252
+ else
253
+ [404, {"Content-Type" => "text/html"}, ["Not Found"]]
254
+ end
255
+ end
256
+ end
257
+ </ruby>
258
+
259
+ Metal applications within +app/metal+ folders in plugins will also be discovered and added to the list
260
+
261
+ Metal applications are an optimization. You should make sure to "understand the related performance implications":http://weblog.rubyonrails.org/2008/12/20/performance-of-rails-metal before using it.
262
+
263
+ h4. Execution Order
264
+
265
+ All Metal Applications are executed by +Rails::Rack::Metal+ middleware, which is a part of the +ActionController::MiddlewareStack+ chain.
266
+
267
+ Here's the primary method responsible for running the Metal applications:
268
+
269
+ <ruby>
270
+ def call(env)
271
+ @metals.keys.each do |app|
272
+ result = app.call(env)
273
+ return result unless result[0].to_i == 404
274
+ end
275
+ @app.call(env)
276
+ end
277
+ </ruby>
278
+
279
+ In the code above, +@metals+ is an ordered hash of metal applications. Due to the default alphabetical ordering, +aaa.rb+ will come before +bbb.rb+ in the metal chain.
280
+
281
+ It is, however, possible to override the default ordering in your environment. Simply add a line like the following to +config/environment.rb+
282
+
283
+ <ruby>
284
+ config.metals = ["Bbb", "Aaa"]
285
+ </ruby>
286
+
287
+ Each string in the array should be the name of your metal class. If you do this then be warned that any metal applications not listed will not be loaded.
288
+
289
+ WARNING: Metal applications cannot return the HTTP Status +404+ to a client, as it is used for continuing the Metal chain execution. Please use normal Rails controllers or a custom middleware if returning +404+ is a requirement.
290
+
291
+ h3. Resources
292
+
293
+ h4. Learning Rack
294
+
295
+ * "Official Rack Website":http://rack.github.com
296
+ * "Introducing Rack":http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html
297
+ * "Ruby on Rack #1 - Hello Rack!":http://m.onkey.org/2008/11/17/ruby-on-rack-1
298
+ * "Ruby on Rack #2 - The Builder":http://m.onkey.org/2008/11/18/ruby-on-rack-2-rack-builder
299
+
300
+ h4. Understanding Middlewares
301
+
302
+ * "Railscast on Rack Middlewares":http://railscasts.com/episodes/151-rack-middleware
303
+
304
+ h3. Changelog
305
+
306
+ "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/58
307
+
308
+ * February 7, 2009: Second version by "Pratik":credits.html#lifo
309
+ * January 11, 2009: First version by "Pratik":credits.html#lifo
@@ -0,0 +1,903 @@
1
+ h2. Rails Routing from the Outside In
2
+
3
+ This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to:
4
+
5
+ * Understand the purpose of routing
6
+ * Decipher the code in +routes.rb+
7
+ * Construct your own routes, using either the classic hash style or the now-preferred RESTful style
8
+ * Identify how a route will map to a controller and action
9
+
10
+ endprologue.
11
+
12
+ h3. The Dual Purpose of Routing
13
+
14
+ Rails routing is a two-way piece of machinery - rather as if you could turn trees into paper, and then turn paper back into trees. Specifically, it both connects incoming HTTP requests to the code in your application's controllers, and helps you generate URLs without having to hard-code them as strings.
15
+
16
+ h4. Connecting URLs to Code
17
+
18
+ When your Rails application receives an incoming HTTP request, say
19
+
20
+ <pre>
21
+ GET /patients/17
22
+ </pre>
23
+
24
+ the routing engine within Rails is the piece of code that dispatches the request to the appropriate spot in your application. In this case, the application would most likely end up running the +show+ action within the +patients+ controller, displaying the details of the patient whose ID is 17.
25
+
26
+ h4. Generating URLs from Code
27
+
28
+ Routing also works in reverse. If your application contains this code:
29
+
30
+ <ruby>
31
+ @patient = Patient.find(17)
32
+ </ruby>
33
+
34
+ <erb>
35
+ <%= link_to "Patient Record", patient_path(@patient) %>
36
+ </erb>
37
+
38
+ Then the routing engine is the piece that translates that to a link to a URL such as +http://example.com/patients/17+. By using routing in this way, you can reduce the brittleness of your application as compared to one with hard-coded URLs, and make your code easier to read and understand.
39
+
40
+ NOTE: Patient needs to be declared as a resource for this style of translation via a named route to be available.
41
+
42
+ h3. Quick Tour of +routes.rb+
43
+
44
+ There are two components to routing in Rails: the routing engine itself, which is supplied as part of Rails, and the file +config/routes.rb+, which contains the actual routes that will be used by your application. Learning exactly what you can put in +routes.rb+ is the main topic of this guide, but before we dig in let's get a quick overview.
45
+
46
+ h4. Processing the File
47
+
48
+ In format, +routes.rb+ is nothing more than one big block sent to +ActionController::Routing::Routes.draw+. Within this block, you can have comments, but it's likely that most of your content will be individual lines of code - each line being a route in your application. You'll find five main types of content in this file:
49
+
50
+ * RESTful Routes
51
+ * Named Routes
52
+ * Nested Routes
53
+ * Regular Routes
54
+ * Default Routes
55
+
56
+ Each of these types of route is covered in more detail later in this guide.
57
+
58
+ The +routes.rb+ file is processed from top to bottom when a request comes in. The request will be dispatched to the first matching route. If there is no matching route, then Rails returns HTTP status 404 to the caller.
59
+
60
+ h4. RESTful Routes
61
+
62
+ RESTful routes take advantage of the built-in REST orientation of Rails to wrap up a lot of routing information in a single declaration. A RESTful route looks like this:
63
+
64
+ <ruby>
65
+ map.resources :books
66
+ </ruby>
67
+
68
+ h4. Named Routes
69
+
70
+ Named routes give you very readable links in your code, as well as handling incoming requests. Here's a typical named route:
71
+
72
+ <ruby>
73
+ map.login '/login', :controller => 'sessions', :action => 'new'
74
+ </ruby>
75
+
76
+ h4. Nested Routes
77
+
78
+ Nested routes let you declare that one resource is contained within another resource. You'll see later on how this translates to URLs and paths in your code. For example, if your application includes parts, each of which belongs to an assembly, you might have this nested route declaration:
79
+
80
+ <ruby>
81
+ map.resources :assemblies do |assemblies|
82
+ assemblies.resources :parts
83
+ end
84
+ </ruby>
85
+
86
+ h4. Regular Routes
87
+
88
+ In many applications, you'll also see non-RESTful routing, which explicitly connects the parts of a URL to a particular action. For example,
89
+
90
+ <ruby>
91
+ map.connect 'parts/:number', :controller => 'inventory', :action => 'show'
92
+ </ruby>
93
+
94
+ h4. Default Routes
95
+
96
+ The default routes are a safety net that catch otherwise-unrouted requests. Many Rails applications will contain this pair of default routes:
97
+
98
+ <ruby>
99
+ map.connect ':controller/:action/:id'
100
+ map.connect ':controller/:action/:id.:format'
101
+ </ruby>
102
+
103
+ These default routes are automatically generated when you create a new Rails application. If you're using RESTful routing for everything in your application, you will probably want to remove them. But be sure you're not using the default routes before you remove them!
104
+
105
+ h3. RESTful Routing: the Rails Default
106
+
107
+ RESTful routing is the current standard for routing in Rails, and it's the one that you should prefer for new applications. It can take a little while to understand how RESTful routing works, but it's worth the effort; your code will be easier to read and you'll be working with Rails, rather than fighting against it, when you use this style of routing.
108
+
109
+ h4. What is REST?
110
+
111
+ The foundation of RESTful routing is generally considered to be Roy Fielding's doctoral thesis, "Architectural Styles and the Design of Network-based Software Architectures":http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm. Fortunately, you need not read this entire document to understand how REST works in Rails. REST, an acronym for Representational State Transfer, boils down to two main principles for our purposes:
112
+
113
+ * Using resource identifiers (which, for the purposes of discussion, you can think of as URLs) to represent resources
114
+ * Transferring representations of the state of that resource between system components.
115
+
116
+ For example, to a Rails application a request such as this:
117
+
118
+ <pre>
119
+ DELETE /photos/17
120
+ </pre>
121
+
122
+ would be understood to refer to a photo resource with the ID of 17, and to indicate a desired action - deleting that resource. REST is a natural style for the architecture of web applications, and Rails makes it even more natural by using conventions to shield you from some of the RESTful complexities.
123
+
124
+ h4. CRUD, Verbs, and Actions
125
+
126
+ In Rails, a RESTful route provides a mapping between HTTP verbs, controller actions, and (implicitly) CRUD operations in a database. A single entry in the routing file, such as
127
+
128
+ <ruby>
129
+ map.resources :photos
130
+ </ruby>
131
+
132
+ creates seven different routes in your application:
133
+
134
+ |_.HTTP verb|_.URL |_.controller|_.action |_.used for|
135
+ |GET |/photos |Photos |index |display a list of all photos|
136
+ |GET |/photos/new |Photos |new |return an HTML form for creating a new photo|
137
+ |POST |/photos |Photos |create |create a new photo|
138
+ |GET |/photos/1 |Photos |show |display a specific photo|
139
+ |GET |/photos/1/edit |Photos |edit |return an HTML form for editing a photo|
140
+ |PUT |/photos/1 |Photos |update |update a specific photo|
141
+ |DELETE |/photos/1 |Photos |destroy |delete a specific photo|
142
+
143
+ For the specific routes (those that reference just a single resource), the identifier for the resource will be available within the corresponding controller action as +params[:id]+.
144
+
145
+ TIP: If you consistently use RESTful routes in your application, you should disable the default routes in +routes.rb+ so that Rails will enforce the mapping between HTTP verbs and routes.
146
+
147
+ h4. URLs and Paths
148
+
149
+ Creating a RESTful route will also make available a pile of helpers within your application:
150
+
151
+ * +photos_url+ and +photos_path+ map to the path for the index and create actions
152
+ * +new_photo_url+ and +new_photo_path+ map to the path for the new action
153
+ * +edit_photo_url+ and +edit_photo_path+ map to the path for the edit action
154
+ * +photo_url+ and +photo_path+ map to the path for the show, update, and destroy actions
155
+
156
+ NOTE: Because routing makes use of the HTTP verb as well as the path in the request to dispatch requests, the seven routes generated by a RESTful routing entry only give rise to four pairs of helpers.
157
+
158
+ In each case, the +_url+ helper generates a string containing the entire URL that the application will understand, while the +_path+ helper generates a string containing the relative path from the root of the application. For example:
159
+
160
+ <ruby>
161
+ photos_url # => "http://www.example.com/photos"
162
+ photos_path # => "/photos"
163
+ </ruby>
164
+
165
+ h4. Defining Multiple Resources at the Same Time
166
+
167
+ If you need to create routes for more than one RESTful resource, you can save a bit of typing by defining them all with a single call to +map.resources+:
168
+
169
+ <ruby>
170
+ map.resources :photos, :books, :videos
171
+ </ruby>
172
+
173
+ This has exactly the same effect as
174
+
175
+ <ruby>
176
+ map.resources :photos
177
+ map.resources :books
178
+ map.resources :videos
179
+ </ruby>
180
+
181
+ h4. Singular Resources
182
+
183
+ You can also apply RESTful routing to singleton resources within your application. In this case, you use +map.resource+ instead of +map.resources+ and the route generation is slightly different. For example, a routing entry of
184
+
185
+ <ruby>
186
+ map.resource :geocoder
187
+ </ruby>
188
+
189
+ creates six different routes in your application:
190
+
191
+ |_.HTTP verb|_.URL |_.controller|_.action |_.used for|
192
+ |GET |/geocoder/new |Geocoders |new |return an HTML form for creating the new geocoder|
193
+ |POST |/geocoder |Geocoders |create |create the new geocoder|
194
+ |GET |/geocoder |Geocoders |show |display the one and only geocoder resource|
195
+ |GET |/geocoder/edit |Geocoders |edit |return an HTML form for editing the geocoder|
196
+ |PUT |/geocoder |Geocoders |update |update the one and only geocoder resource|
197
+ |DELETE |/geocoder |Geocoders |destroy |delete the geocoder resource|
198
+
199
+ NOTE: Even though the name of the resource is singular in +routes.rb+, the matching controller is still plural.
200
+
201
+ A singular RESTful route generates an abbreviated set of helpers:
202
+
203
+ * +new_geocoder_url+ and +new_geocoder_path+ map to the path for the new action
204
+ * +edit_geocoder_url+ and +edit_geocoder_path+ map to the path for the edit action
205
+ * +geocoder_url+ and +geocoder_path+ map to the path for the create, show, update, and destroy actions
206
+
207
+ h4. Customizing Resources
208
+
209
+ Although the conventions of RESTful routing are likely to be sufficient for many applications, there are a number of ways to customize the way that RESTful routes work. These options include:
210
+
211
+ * +:controller+
212
+ * +:singular+
213
+ * +:requirements+
214
+ * +:conditions+
215
+ * +:as+
216
+ * +:path_names+
217
+ * +:path_prefix+
218
+ * +:name_prefix+
219
+ * +:only+
220
+ * +:except+
221
+
222
+ You can also add additional routes via the +:member+ and +:collection+ options, which are discussed later in this guide.
223
+
224
+ h5. Using +:controller+
225
+
226
+ The +:controller+ option lets you use a controller name that is different from the public-facing resource name. For example, this routing entry:
227
+
228
+ <ruby>
229
+ map.resources :photos, :controller => "images"
230
+ </ruby>
231
+
232
+ will recognize incoming URLs containing +photo+ but route the requests to the Images controller:
233
+
234
+ |_.HTTP verb|_.URL |_.controller|_.action |_.used for|
235
+ |GET |/photos |Images |index |display a list of all images|
236
+ |GET |/photos/new |Images |new |return an HTML form for creating a new image|
237
+ |POST |/photos |Images |create |create a new image|
238
+ |GET |/photos/1 |Images |show |display a specific image|
239
+ |GET |/photos/1/edit |Images |edit |return an HTML form for editing a image|
240
+ |PUT |/photos/1 |Images |update |update a specific image|
241
+ |DELETE |/photos/1 |Images |destroy |delete a specific image|
242
+
243
+ NOTE: The helpers will be generated with the name of the resource, not the name of the controller. So in this case, you'd still get +photos_path+, +new_photo_path+, and so on.
244
+
245
+ h4. Controller Namespaces and Routing
246
+
247
+ Rails allows you to group your controllers into namespaces by saving them in folders underneath +app/controllers+. The +:controller+ option provides a convenient way to use these routes. For example, you might have a resource whose controller is purely for admin users in the +admin+ folder:
248
+
249
+ <ruby>
250
+ map.resources :adminphotos, :controller => "admin/photos"
251
+ </ruby>
252
+
253
+ If you use controller namespaces, you need to be aware of a subtlety in the Rails routing code: it always tries to preserve as much of the namespace from the previous request as possible. For example, if you are on a view generated from the +adminphoto_path+ helper, and you follow a link generated with +&lt;%= link_to "show", adminphoto(1) %&gt;+ you will end up on the view generated by +admin/photos/show+, but you will also end up in the same place if you have +&lt;%= link_to "show", {:controller => "photos", :action => "show"} %&gt;+ because Rails will generate the show URL relative to the current URL.
254
+
255
+ TIP: If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: +&lt;%= link_to "show", {:controller => "/photos", :action => "show"} %&gt;+
256
+
257
+ You can also specify a controller namespace with the +:namespace+ option instead of a path:
258
+
259
+ <ruby>
260
+ map.resources :adminphotos, :namespace => "admin", :controller => "photos"
261
+ </ruby>
262
+
263
+ This can be especially useful when combined with +with_options+ to map multiple namespaced routes together:
264
+
265
+ <ruby>
266
+ map.with_options(:namespace => "admin") do |admin|
267
+ admin.resources :photos, :videos
268
+ end
269
+ </ruby>
270
+
271
+ That would give you routing for +admin/photos+ and +admin/videos+ controllers.
272
+
273
+ h5. Using +:singular+
274
+
275
+ If for some reason Rails isn't doing what you want in converting the plural resource name to a singular name in member routes, you can override its judgment with the +:singular+ option:
276
+
277
+ <ruby>
278
+ map.resources :teeth, :singular => "tooth"
279
+ </ruby>
280
+
281
+ TIP: Depending on the other code in your application, you may prefer to add additional rules to the +Inflector+ class instead.
282
+
283
+ h5. Using +:requirements+
284
+
285
+ You can use the +:requirements+ option in a RESTful route to impose a format on the implied +:id+ parameter in the singular routes. For example:
286
+
287
+ <ruby>
288
+ map.resources :photos, :requirements => {:id => /[A-Z][A-Z][0-9]+/}
289
+ </ruby>
290
+
291
+ This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, +/photos/1+ would no longer be recognized by this route, but +/photos/RR27+ would.
292
+
293
+ h5. Using +:conditions+
294
+
295
+ Conditions in Rails routing are currently used only to set the HTTP verb for individual routes. Although in theory you can set this for RESTful routes, in practice there is no good reason to do so. (You'll learn more about conditions in the discussion of classic routing later in this guide.)
296
+
297
+ h5. Using +:as+
298
+
299
+ The +:as+ option lets you override the normal naming for the actual generated paths. For example:
300
+
301
+ <ruby>
302
+ map.resources :photos, :as => "images"
303
+ </ruby>
304
+
305
+ will recognize incoming URLs containing +image+ but route the requests to the Photos controller:
306
+
307
+ |_.HTTP verb|_.URL |_.controller|_.action |_:used for|
308
+ |GET |/images |Photos |index |display a list of all photos|
309
+ |GET |/images/new |Photos |new |return an HTML form for creating a new photo|
310
+ |POST |/images |Photos |create |create a new photo|
311
+ |GET |/images/1 |Photos |show |display a specific photo|
312
+ |GET |/images/1/edit |Photos |edit |return an HTML form for editing a photo|
313
+ |PUT |/images/1 |Photos |update |update a specific photo|
314
+ |DELETE |/images/1 |Photos |destroy |delete a specific photo|
315
+
316
+ NOTE: The helpers will be generated with the name of the resource, not the path name. So in this case, you'd still get +photos_path+, +new_photo_path+, and so on.
317
+
318
+ h5. Using +:path_names+
319
+
320
+ The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in URLs:
321
+
322
+ <ruby>
323
+ map.resources :photos, :path_names => { :new => 'make', :edit => 'change' }
324
+ </ruby>
325
+
326
+ This would cause the routing to recognize URLs such as
327
+
328
+ <pre>
329
+ /photos/make
330
+ /photos/1/change
331
+ </pre>
332
+
333
+ NOTE: The actual action names aren't changed by this option; the two URLs shown would still route to the new and edit actions.
334
+
335
+ TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can set a default in your environment:
336
+
337
+ <ruby>
338
+ config.action_controller.resources_path_names = { :new => 'make', :edit => 'change' }
339
+ </ruby>
340
+
341
+ h5. Using +:path_prefix+
342
+
343
+ The +:path_prefix+ option lets you add additional parameters that will be prefixed to the recognized paths. For example, suppose each photo in your application belongs to a particular photographer. In that case, you might declare this route:
344
+
345
+ <ruby>
346
+ map.resources :photos, :path_prefix => '/photographers/:photographer_id'
347
+ </ruby>
348
+
349
+ Routes recognized by this entry would include:
350
+
351
+ <pre>
352
+ /photographers/1/photos/2
353
+ /photographers/1/photos
354
+ </pre>
355
+
356
+ NOTE: In most cases, it's simpler to recognize URLs of this sort by creating nested resources, as discussed in the next section.
357
+
358
+ NOTE: You can also use +:path_prefix+ with non-RESTful routes.
359
+
360
+ h5. Using +:name_prefix+
361
+
362
+ You can use the :name_prefix option to avoid collisions between routes. This is most useful when you have two resources with the same name that use +:path_prefix+ to map differently. For example:
363
+
364
+ <ruby>
365
+ map.resources :photos, :path_prefix => '/photographers/:photographer_id',
366
+ :name_prefix => 'photographer_'
367
+ map.resources :photos, :path_prefix => '/agencies/:agency_id',
368
+ :name_prefix => 'agency_'
369
+ </ruby>
370
+
371
+ This combination will give you route helpers such as +photographer_photos_path+ and +agency_edit_photo_path+ to use in your code.
372
+
373
+ NOTE: You can also use +:name_prefix+ with non-RESTful routes.
374
+
375
+ h5. Using +:only+ and +:except+
376
+
377
+ By default, Rails creates routes for all seven of the default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the +:only+ and +:except+ options to fine-tune this behavior. The +:only+ option specifies that only certain routes should be generated:
378
+
379
+ <ruby>
380
+ map.resources :photos, :only => [:index, :show]
381
+ </ruby>
382
+
383
+ With this declaration, a +GET+ request to +/photos+ would succeed, but a +POST+ request to +/photos+ (which would ordinarily be routed to the create action) will fail.
384
+
385
+ The +:except+ option specifies a route or list of routes that should _not_ be generated:
386
+
387
+ <ruby>
388
+ map.resources :photos, :except => :destroy
389
+ </ruby>
390
+
391
+ In this case, all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/<em>id</em>+) will be generated.
392
+
393
+ In addition to an action or a list of actions, you can also supply the special symbols +:all+ or +:none+ to the +:only+ and +:except+ options.
394
+
395
+ TIP: If your application has many RESTful routes, using +:only+ and +:except+ to generate only the routes that you actually need can cut down on memory use and speed up the routing process.
396
+
397
+ h4. Nested Resources
398
+
399
+ It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
400
+
401
+ <ruby>
402
+ class Magazine < ActiveRecord::Base
403
+ has_many :ads
404
+ end
405
+
406
+ class Ad < ActiveRecord::Base
407
+ belongs_to :magazine
408
+ end
409
+ </ruby>
410
+
411
+ Each ad is logically subservient to one magazine. Nested routes allow you to capture this relationship in your routing. In this case, you might include this route declaration:
412
+
413
+ <ruby>
414
+ map.resources :magazines do |magazine|
415
+ magazine.resources :ads
416
+ end
417
+ </ruby>
418
+
419
+ TIP: Further below you'll learn about a convenient shortcut for this construct:<br/>+map.resources :magazines, :has_many => :ads+.
420
+
421
+ In addition to the routes for magazines, this declaration will also create routes for ads, each of which requires the specification of a magazine in the URL:
422
+
423
+ |_.HTTP verb|_.URL |_.controller|_.action |_.used for|
424
+ |GET |/magazines/1/ads |Ads |index |display a list of all ads for a specific magazine|
425
+ |GET |/magazines/1/ads/new |Ads |new |return an HTML form for creating a new ad belonging to a specific magazine|
426
+ |POST |/magazines/1/ads |Ads |create |create a new ad belonging to a specific magazine|
427
+ |GET |/magazines/1/ads/1 |Ads |show |display a specific ad belonging to a specific magazine|
428
+ |GET |/magazines/1/ads/1/edit |Ads |edit |return an HTML form for editing an ad belonging to a specific magazine|
429
+ |PUT |/magazines/1/ads/1 |Ads |update |update a specific ad belonging to a specific magazine|
430
+ |DELETE |/magazines/1/ads/1 |Ads |destroy |delete a specific ad belonging to a specific magazine|
431
+
432
+
433
+ This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+.
434
+
435
+ h5. Using +:name_prefix+
436
+
437
+ The +:name_prefix+ option overrides the automatically-generated prefix in nested route helpers. For example,
438
+
439
+ <ruby>
440
+ map.resources :magazines do |magazine|
441
+ magazine.resources :ads, :name_prefix => 'periodical'
442
+ end
443
+ </ruby>
444
+
445
+ This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+. You can even use +:name_prefix+ to suppress the prefix entirely:
446
+
447
+ <ruby>
448
+ map.resources :magazines do |magazine|
449
+ magazine.resources :ads, :name_prefix => nil
450
+ end
451
+ </ruby>
452
+
453
+ This will create routing helpers such as +ads_url+ and +edit_ad_path+. Note that calling these will still require supplying an article id:
454
+
455
+ <ruby>
456
+ ads_url(@magazine)
457
+ edit_ad_path(@magazine, @ad)
458
+ </ruby>
459
+
460
+ h5. Using +:has_one+ and +:has_many+
461
+
462
+ The +:has_one+ and +:has_many+ options provide a succinct notation for simple nested routes. Use +:has_one+ to nest a singleton resource, or +:has_many+ to nest a plural resource:
463
+
464
+ <ruby>
465
+ map.resources :photos, :has_one => :photographer, :has_many => [:publications, :versions]
466
+ </ruby>
467
+
468
+ This has the same effect as this set of declarations:
469
+
470
+ <ruby>
471
+ map.resources :photos do |photo|
472
+ photo.resource :photographer
473
+ photo.resources :publications
474
+ photo.resources :versions
475
+ end
476
+ </ruby>
477
+
478
+ h5. Limits to Nesting
479
+
480
+ You can nest resources within other nested resources if you like. For example:
481
+
482
+ <ruby>
483
+ map.resources :publishers do |publisher|
484
+ publisher.resources :magazines do |magazine|
485
+ magazine.resources :photos
486
+ end
487
+ end
488
+ </ruby>
489
+
490
+ However, without the use of +name_prefix => nil+, deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize URLs such as
491
+
492
+ <pre>
493
+ /publishers/1/magazines/2/photos/3
494
+ </pre>
495
+
496
+ The corresponding route helper would be +publisher_magazine_photo_url+, requiring you to specify objects at all three levels. Indeed, this situation is confusing enough that a popular "article":http://weblog.jamisbuck.org/2007/2/5/nesting-resources by Jamis Buck proposes a rule of thumb for good Rails design:
497
+
498
+ TIP: _Resources should never be nested more than 1 level deep._
499
+
500
+ h5. Shallow Nesting
501
+
502
+ The +:shallow+ option provides an elegant solution to the difficulties of deeply-nested routes. If you specify this option at any level of routing, then paths for nested resources which reference a specific member (that is, those with an +:id+ parameter) will not use the parent path prefix or name prefix. To see what this means, consider this set of routes:
503
+
504
+ <ruby>
505
+ map.resources :publishers, :shallow => true do |publisher|
506
+ publisher.resources :magazines do |magazine|
507
+ magazine.resources :photos
508
+ end
509
+ end
510
+ </ruby>
511
+
512
+ This will enable recognition of (among others) these routes:
513
+
514
+ <pre>
515
+ /publishers/1 ==> publisher_path(1)
516
+ /publishers/1/magazines ==> publisher_magazines_path(1)
517
+ /magazines/2 ==> magazine_path(2)
518
+ /magazines/2/photos ==> magazines_photos_path(2)
519
+ /photos/3 ==> photo_path(3)
520
+ </pre>
521
+
522
+ With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with. If you like, you can combine shallow nesting with the +:has_one+ and +:has_many+ options:
523
+
524
+ <ruby>
525
+ map.resources :publishers, :has_many => { :magazines => :photos }, :shallow => true
526
+ </ruby>
527
+
528
+ h4. Route Generation from Arrays
529
+
530
+ In addition to using the generated routing helpers, Rails can also generate RESTful routes from an array of parameters. For example, suppose you have a set of routes generated with these entries in routes.rb:
531
+
532
+ <ruby>
533
+ map.resources :magazines do |magazine|
534
+ magazine.resources :ads
535
+ end
536
+ </ruby>
537
+
538
+ Rails will generate helpers such as magazine_ad_path that you can use in building links:
539
+
540
+ <ruby>
541
+ <%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %>
542
+ </ruby>
543
+
544
+ Another way to refer to the same route is with an array of objects:
545
+
546
+ <ruby>
547
+ <%= link_to "Ad details", [@magazine, @ad] %>
548
+ </ruby>
549
+
550
+ This format is especially useful when you might not know until runtime which of several types of object will be used in a particular link.
551
+
552
+ h4. Namespaced Resources
553
+
554
+ It's possible to do some quite complex things by combining +:path_prefix+ and +:name_prefix+. For example, you can use the combination of these two options to move administrative resources to their own folder in your application:
555
+
556
+ <ruby>
557
+ map.resources :photos, :path_prefix => 'admin', :controller => 'admin/photos'
558
+ map.resources :tags, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_tags'
559
+ map.resources :ratings, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_ratings'
560
+ </ruby>
561
+
562
+ The good news is that if you find yourself using this level of complexity, you can stop. Rails supports _namespaced resources_ to make placing resources in their own folder a snap. Here's the namespaced version of those same three routes:
563
+
564
+ <ruby>
565
+ map.namespace(:admin) do |admin|
566
+ admin.resources :photos,
567
+ :has_many => { :tags, :ratings}
568
+ end
569
+ </ruby>
570
+
571
+ As you can see, the namespaced version is much more succinct than the one that spells everything out - but it still creates the same routes. For example, you'll get +admin_photos_url+ that expects to find an +Admin::PhotosController+ and that matches +admin/photos+, and +admin_photos_ratings_path+ that matches +/admin/photos/_photo_id_/ratings+, expecting to use +Admin::RatingsController+. Even though you're not specifying +path_prefix+ explicitly, the routing code will calculate the appropriate +path_prefix+ from the route nesting.
572
+
573
+ h4. Adding More RESTful Actions
574
+
575
+ You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional member routes (those which apply to a single instance of the resource), additional new routes (those that apply to creating a new resource), or additional collection routes (those which apply to the collection of resources as a whole).
576
+
577
+ h5. Adding Member Routes
578
+
579
+ To add a member route, use the +:member+ option:
580
+
581
+ <ruby>
582
+ map.resources :photos, :member => { :preview => :get }
583
+ </ruby>
584
+
585
+ This will enable Rails to recognize URLs such as +/photos/1/preview+ using the GET HTTP verb, and route them to the preview action of the Photos controller. It will also create a +preview_photo+ route helper.
586
+
587
+ Within the hash of member routes, each route name specifies the HTTP verb that it will recognize. You can use +:get+, +:put+, +:post+, +:delete+, or +:any+ here. You can also specify an array of methods, if you need more than one but you don't want to allow just anything:
588
+
589
+ <ruby>
590
+ map.resources :photos, :member => { :prepare => [:get, :post] }
591
+ </ruby>
592
+
593
+ h5. Adding Collection Routes
594
+
595
+ To add a collection route, use the +:collection+ option:
596
+
597
+ <ruby>
598
+ map.resources :photos, :collection => { :search => :get }
599
+ </ruby>
600
+
601
+ This will enable Rails to recognize URLs such as +/photos/search+ using the GET HTTP verb, and route them to the search action of the Photos controller. It will also create a +search_photos+ route helper.
602
+
603
+ Just as with member routes, you can specify an array of methods for a collection route:
604
+
605
+ <ruby>
606
+ map.resources :photos, :collection => { :search => [:get, :post] }
607
+ </ruby>
608
+
609
+ h5. Adding New Routes
610
+
611
+ To add a new route (one that creates a new resource), use the +:new+ option:
612
+
613
+ <ruby>
614
+ map.resources :photos, :new => { :upload => :post }
615
+ </ruby>
616
+
617
+ This will enable Rails to recognize URLs such as +/photos/upload+ using the POST HTTP verb, and route them to the upload action of the Photos controller. It will also create a +upload_photos+ route helper.
618
+
619
+ TIP: If you want to redefine the verbs accepted by one of the standard actions, you can do so by explicitly mapping that action. For example:<br/>+map.resources :photos, :new => { :new => :any }+<br/>This will allow the new action to be invoked by any request to +photos/new+, no matter what HTTP verb you use.
620
+
621
+ h5. A Note of Caution
622
+
623
+ If you find yourself adding many extra actions to a RESTful route, it's time to stop and ask yourself whether you're disguising the presence of another resource that would be better split off on its own. When the +:member+ and +:collection+ hashes become a dumping-ground, RESTful routes lose the advantage of easy readability that is one of their strongest points.
624
+
625
+ h3. Regular Routes
626
+
627
+ In addition to RESTful routing, Rails supports regular routing - a way to map URLs to controllers and actions. With regular routing, you don't get the masses of routes automatically generated by RESTful routing. Instead, you must set up each route within your application separately.
628
+
629
+ While RESTful routing has become the Rails standard, there are still plenty of places where the simpler regular routing works fine. You can even mix the two styles within a single application. In general, you should prefer RESTful routing _when possible_, because it will make parts of your application easier to write. But there's no need to try to shoehorn every last piece of your application into a RESTful framework if that's not a good fit.
630
+
631
+ h4. Bound Parameters
632
+
633
+ When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: +:controller+ maps to the name of a controller in your application, and +:action+ maps to the name of an action within that controller. For example, consider one of the default Rails routes:
634
+
635
+ <ruby>
636
+ map.connect ':controller/:action/:id'
637
+ </ruby>
638
+
639
+ If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +Photos+ controller, and to make the final parameter (1) available as +params[:id]+.
640
+
641
+ h4. Wildcard Components
642
+
643
+ You can set up as many wildcard symbols within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the matching action as part of the params hash. So, if you set up this route:
644
+
645
+ <ruby>
646
+ map.connect ':controller/:action/:id/:user_id'
647
+ </ruby>
648
+
649
+ An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be set to 2.
650
+
651
+ h4. Static Text
652
+
653
+ You can specify static text when creating a route. In this case, the static text is used only for matching the incoming requests:
654
+
655
+ <ruby>
656
+ map.connect ':controller/:action/:id/with_user/:user_id'
657
+ </ruby>
658
+
659
+ This route would respond to URLs such as +/photos/show/1/with_user/2+.
660
+
661
+ h4. Querystring Parameters
662
+
663
+ Rails routing automatically picks up querystring parameters and makes them available in the +params+ hash. For example, with this route:
664
+
665
+ <ruby>
666
+ map.connect ':controller/:action/:id'
667
+ </ruby>
668
+
669
+ An incoming URL of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be equal to 2.
670
+
671
+ h4. Defining Defaults
672
+
673
+ You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply defaults for these two parameters in a hash:
674
+
675
+ <ruby>
676
+ map.connect 'photos/:id', :controller => 'photos', :action => 'show'
677
+ </ruby>
678
+
679
+ With this route, an incoming URL of +/photos/12+ would be dispatched to the +show+ action within the +Photos+ controller.
680
+
681
+ You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that are not explicitly defined elsewhere in the route. For example:
682
+
683
+ <ruby>
684
+ map.connect 'photos/:id', :controller => 'photos', :action => 'show',
685
+ :defaults => { :format => 'jpg' }
686
+ </ruby>
687
+
688
+ With this route, an incoming URL of +photos/12+ would be dispatched to the +show+ action within the +Photos+ controller, and +params[:format]+ will be set to +jpg+.
689
+
690
+ h4. Named Routes
691
+
692
+ Regular routes need not use the +connect+ method. You can use any other name here to create a _named route_. For example,
693
+
694
+ <ruby>
695
+ map.logout '/logout', :controller => 'sessions', :action => 'destroy'
696
+ </ruby>
697
+
698
+ This will do two things. First, requests to +/logout+ will be sent to the +destroy+ method of the +Sessions+ controller. Second, Rails will maintain the +logout_path+ and +logout_url+ helpers for use within your code.
699
+
700
+ h4. Route Requirements
701
+
702
+ You can use the +:requirements+ option to enforce a format for any parameter in a route:
703
+
704
+ <ruby>
705
+ map.connect 'photo/:id', :controller => 'photos', :action => 'show',
706
+ :requirements => { :id => /[A-Z]\d{5}/ }
707
+ </ruby>
708
+
709
+ This route would respond to URLs such as +/photo/A12345+. You can more succinctly express the same route this way:
710
+
711
+ <ruby>
712
+ map.connect 'photo/:id', :controller => 'photos', :action => 'show',
713
+ :id => /[A-Z]\d{5}/
714
+ </ruby>
715
+
716
+ h4. Route Conditions
717
+
718
+ Route conditions (introduced with the +:conditions+ option) are designed to implement restrictions on routes. Currently, the only supported restriction is +:method+:
719
+
720
+ <ruby>
721
+ map.connect 'photo/:id', :controller => 'photos', :action => 'show',
722
+ :conditions => { :method => :get }
723
+ </ruby>
724
+
725
+ As with conditions in RESTful routes, you can specify +:get+, +:post+, +:put+, +:delete+, or +:any+ for the acceptable method.
726
+
727
+ h4. Route Globbing
728
+
729
+ Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example
730
+
731
+ <ruby>
732
+ map.connect 'photo/*other', :controller => 'photos', :action => 'unknown',
733
+ </ruby>
734
+
735
+ This route would match +photo/12+ or +/photo/long/path/to/12+ equally well, creating an array of path segments as the value of +params[:other]+.
736
+
737
+ h4. Route Options
738
+
739
+ You can use +:with_options+ to simplify defining groups of similar routes:
740
+
741
+ <ruby>
742
+ map.with_options :controller => 'photo' do |photo|
743
+ photo.list '', :action => 'index'
744
+ photo.delete ':id/delete', :action => 'delete'
745
+ photo.edit ':id/edit', :action => 'edit'
746
+ end
747
+ </ruby>
748
+
749
+ The importance of +map.with_options+ has declined with the introduction of RESTful routes.
750
+
751
+ h3. Formats and +respond_to+
752
+
753
+ There's one more way in which routing can do different things depending on differences in the incoming HTTP request: by issuing a response that corresponds to what the request specifies that it will accept. In Rails routing, you can control this with the special +:format+ parameter in the route.
754
+
755
+ For instance, consider the second of the default routes in the boilerplate +routes.rb+ file:
756
+
757
+ <ruby>
758
+ map.connect ':controller/:action/:id.:format'
759
+ </ruby>
760
+
761
+ This route matches requests such as +/photo/edit/1.xml+ or +/photo/show/2.rss+. Within the appropriate action code, you can issue different responses depending on the requested format:
762
+
763
+ <ruby>
764
+ respond_to do |format|
765
+ format.html # return the default template for HTML
766
+ format.xml { render :xml => @photo.to_xml }
767
+ end
768
+ </ruby>
769
+
770
+ h4. Specifying the Format with an HTTP Header
771
+
772
+ If there is no +:format+ parameter in the route, Rails will automatically look at the HTTP Accept header to determine the desired format.
773
+
774
+ h4. Recognized MIME types
775
+
776
+ By default, Rails recognizes +html+, +text+, +json+, +csv+, +xml+, +rss+, +atom+, and +yaml+ as acceptable response types. If you need types beyond this, you can register them in your environment:
777
+
778
+ <ruby>
779
+ Mime::Type.register "image/jpg", :jpg
780
+ </ruby>
781
+
782
+ h3. The Default Routes
783
+
784
+ When you create a new Rails application, +routes.rb+ is initialized with two default routes:
785
+
786
+ <ruby>
787
+ map.connect ':controller/:action/:id'
788
+ map.connect ':controller/:action/:id.:format'
789
+ </ruby>
790
+
791
+ These routes provide reasonable defaults for many URLs, if you're not using RESTful routing.
792
+
793
+ NOTE: The default routes will make every action of every controller in your application accessible to GET requests. If you've designed your application to make consistent use of RESTful and named routes, you should comment out the default routes to prevent access to your controllers through the wrong verbs. If you've had the default routes enabled during development, though, you need to be sure that you haven't unwittingly depended on them somewhere in your application - otherwise you may find mysterious failures when you disable them.
794
+
795
+ h3. The Empty Route
796
+
797
+ Don't confuse the default routes with the empty route. The empty route has one specific purpose: to route requests that come in to the root of the web site. For example, if your site is example.com, then requests to +http://example.com+ or +http://example.com/+ will be handled by the empty route.
798
+
799
+ h4. Using +map.root+
800
+
801
+ The preferred way to set up the empty route is with the +map.root+ command:
802
+
803
+ <ruby>
804
+ map.root :controller => "pages", :action => "main"
805
+ </ruby>
806
+
807
+ The use of the +root+ method tells Rails that this route applies to requests for the root of the site.
808
+
809
+ For better readability, you can specify an already-created route in your call to +map.root+:
810
+
811
+ <ruby>
812
+ map.index 'index', :controller => "pages", :action => "main"
813
+ map.root :index
814
+ </ruby>
815
+
816
+ Because of the top-down processing of the file, the named route must be specified _before_ the call to +map.root+.
817
+
818
+ h4. Connecting the Empty String
819
+
820
+ You can also specify an empty route by explicitly connecting the empty string:
821
+
822
+ <ruby>
823
+ map.connect '', :controller => "pages", :action => "main"
824
+ </ruby>
825
+
826
+ TIP: If the empty route does not seem to be working in your application, make sure that you have deleted the file +public/index.html+ from your Rails tree.
827
+
828
+ h3. Inspecting and Testing Routes
829
+
830
+ Routing in your application should not be a "black box" that you never open. Rails offers built-in tools for both inspecting and testing routes.
831
+
832
+ h4. Seeing Existing Routes with +rake+
833
+
834
+ If you want a complete list of all of the available routes in your application, run the +rake routes+ command. This will dump all of your routes to the console, in the same order that they appear in +routes.rb+. For each route, you'll see:
835
+
836
+ * The route name (if any)
837
+ * The HTTP verb used (if the route doesn't respond to all verbs)
838
+ * The URL pattern
839
+ * The routing parameters that will be generated by this URL
840
+
841
+ For example, here's a small section of the +rake routes+ output for a RESTful route:
842
+
843
+ <pre>
844
+ users GET /users {:controller=>"users", :action=>"index"}
845
+ formatted_users GET /users.:format {:controller=>"users", :action=>"index"}
846
+ POST /users {:controller=>"users", :action=>"create"}
847
+ POST /users.:format {:controller=>"users", :action=>"create"}
848
+ </pre>
849
+
850
+ TIP: You'll find that the output from +rake routes+ is much more readable if you widen your terminal window until the output lines don't wrap.
851
+
852
+ h4. Testing Routes
853
+
854
+ Routes should be included in your testing strategy (just like the rest of your application). Rails offers three "built-in assertions":http://api.rubyonrails.org/classes/ActionController/Assertions/RoutingAssertions.html designed to make testing routes simpler:
855
+
856
+ * +assert_generates+
857
+ * +assert_recognizes+
858
+ * +assert_routing+
859
+
860
+ h5. The +assert_generates+ Assertion
861
+
862
+ Use +assert_generates+ to assert that a particular set of options generate a particular path. You can use this with default routes or custom routes
863
+
864
+ <ruby>
865
+ assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" }
866
+ assert_generates "/about", :controller => "pages", :action => "about"
867
+ </ruby>
868
+
869
+ h5. The +assert_recognizes+ Assertion
870
+
871
+ The +assert_recognizes+ assertion is the inverse of +assert_generates+. It asserts that Rails recognizes the given path and routes it to a particular spot in your application.
872
+
873
+ <ruby>
874
+ assert_recognizes { :controller => "photos", :action => "show", :id => "1" }, "/photos/1"
875
+ </ruby>
876
+
877
+ You can supply a +:method+ argument to specify the HTTP verb:
878
+
879
+ <ruby>
880
+ assert_recognizes { :controller => "photos", :action => "create" }, { :path => "photos", :method => :post }
881
+ </ruby>
882
+
883
+ You can also use the RESTful helpers to test recognition of a RESTful route:
884
+
885
+ <ruby>
886
+ assert_recognizes new_photo_url, { :path => "photos", :method => :post }
887
+ </ruby>
888
+
889
+ h5. The +assert_routing+ Assertion
890
+
891
+ The +assert_routing+ assertion checks the route both ways: it tests that the path generates the options, and that the options generate the path. Thus, it combines the functions of +assert_generates+ and +assert_recognizes+.
892
+
893
+ <ruby>
894
+ assert_routing { :path => "photos", :method => :post }, { :controller => "photos", :action => "create" }
895
+ </ruby>
896
+
897
+ h3. Changelog
898
+
899
+ "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3
900
+
901
+ * October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy
902
+ * September 23, 2008: Added section on namespaced controllers and routing, by "Mike Gunderloy":credits.html#mgunderloy
903
+ * September 10, 2008: initial version by "Mike Gunderloy":credits.html#mgunderloy