railties 3.0.0.beta2 → 3.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -2
- data/guides/{images → assets/images}/belongs_to.png +0 -0
- data/guides/{images → assets/images}/book_icon.gif +0 -0
- data/guides/{images → assets/images}/bullet.gif +0 -0
- data/guides/{images → assets/images}/challenge.png +0 -0
- data/guides/{images → assets/images}/chapters_icon.gif +0 -0
- data/guides/{images → assets/images}/check_bullet.gif +0 -0
- data/guides/{images → assets/images}/credits_pic_blank.gif +0 -0
- data/guides/{images → assets/images}/csrf.png +0 -0
- data/guides/{images → assets/images}/customized_error_messages.png +0 -0
- data/guides/{images → assets/images}/edge_badge.png +0 -0
- data/guides/{images → assets/images}/error_messages.png +0 -0
- data/guides/{images → assets/images}/feature_tile.gif +0 -0
- data/guides/{images → assets/images}/footer_tile.gif +0 -0
- data/guides/{images → assets/images}/fxn.png +0 -0
- data/guides/{images → assets/images}/grey_bullet.gif +0 -0
- data/guides/{images → assets/images}/habtm.png +0 -0
- data/guides/{images → assets/images}/has_many.png +0 -0
- data/guides/{images → assets/images}/has_many_through.png +0 -0
- data/guides/{images → assets/images}/has_one.png +0 -0
- data/guides/{images → assets/images}/has_one_through.png +0 -0
- data/guides/{images → assets/images}/header_backdrop.png +0 -0
- data/guides/{images → assets/images}/header_tile.gif +0 -0
- data/guides/{images → assets/images}/i18n/demo_localized_pirate.png +0 -0
- data/guides/{images → assets/images}/i18n/demo_translated_en.png +0 -0
- data/guides/{images → assets/images}/i18n/demo_translated_pirate.png +0 -0
- data/guides/{images → assets/images}/i18n/demo_translation_missing.png +0 -0
- data/guides/{images → assets/images}/i18n/demo_untranslated.png +0 -0
- data/guides/{images → assets/images}/icons/README +0 -0
- data/guides/{images → assets/images}/icons/callouts/1.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/10.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/11.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/12.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/13.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/14.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/15.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/2.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/3.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/4.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/5.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/6.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/7.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/8.png +0 -0
- data/guides/{images → assets/images}/icons/callouts/9.png +0 -0
- data/guides/{images → assets/images}/icons/caution.png +0 -0
- data/guides/{images → assets/images}/icons/example.png +0 -0
- data/guides/{images → assets/images}/icons/home.png +0 -0
- data/guides/{images → assets/images}/icons/important.png +0 -0
- data/guides/{images → assets/images}/icons/next.png +0 -0
- data/guides/{images → assets/images}/icons/note.png +0 -0
- data/guides/{images → assets/images}/icons/prev.png +0 -0
- data/guides/{images → assets/images}/icons/tip.png +0 -0
- data/guides/{images → assets/images}/icons/up.png +0 -0
- data/guides/{images → assets/images}/icons/warning.png +0 -0
- data/guides/assets/images/jaimeiniesta.jpg +0 -0
- data/guides/{images → assets/images}/nav_arrow.gif +0 -0
- data/guides/{images → assets/images}/polymorphic.png +0 -0
- data/guides/{images → assets/images}/posts_index.png +0 -0
- data/guides/{images → assets/images}/rails_guides_logo.gif +0 -0
- data/guides/{images → assets/images}/rails_logo_remix.gif +0 -0
- data/guides/{images → assets/images}/rails_welcome.png +0 -0
- data/guides/{images → assets/images}/session_fixation.png +0 -0
- data/guides/{images → assets/images}/tab_grey.gif +0 -0
- data/guides/{images → assets/images}/tab_info.gif +0 -0
- data/guides/{images → assets/images}/tab_note.gif +0 -0
- data/guides/{images → assets/images}/tab_red.gif +0 -0
- data/guides/{images → assets/images}/tab_yellow.gif +0 -0
- data/guides/{images → assets/images}/tab_yellow.png +0 -0
- data/guides/{images → assets/images}/validation_error_messages.png +0 -0
- data/guides/{files → assets}/javascripts/code_highlighter.js +0 -0
- data/guides/{files → assets}/javascripts/guides.js +0 -0
- data/guides/{files → assets}/javascripts/highlighters.js +0 -0
- data/guides/{files → assets}/stylesheets/main.css +26 -15
- data/guides/{files → assets}/stylesheets/print.css +0 -0
- data/guides/{files → assets}/stylesheets/reset.css +0 -0
- data/guides/{files → assets}/stylesheets/style.css +0 -0
- data/guides/{files → assets}/stylesheets/syntax.css +0 -0
- data/guides/rails_guides/generator.rb +79 -29
- data/guides/rails_guides/helpers.rb +2 -2
- data/guides/rails_guides/indexer.rb +24 -11
- data/guides/source/2_2_release_notes.textile +1 -1
- data/guides/source/3_0_release_notes.textile +27 -1
- data/guides/source/action_controller_overview.textile +7 -7
- data/guides/source/action_view_overview.textile +15 -15
- data/guides/source/active_record_querying.textile +4 -3
- data/guides/source/active_support_core_extensions.textile +6 -6
- data/guides/source/activerecord_validations_callbacks.textile +1 -1
- data/guides/source/association_basics.textile +83 -82
- data/guides/source/command_line.textile +16 -12
- data/guides/source/configuring.textile +1 -1
- data/guides/source/contribute.textile +1 -1
- data/guides/source/contributing_to_rails.textile +3 -4
- data/guides/source/credits.html.erb +64 -0
- data/guides/source/debugging_rails_applications.textile +2 -1
- data/guides/source/form_helpers.textile +15 -13
- data/guides/source/getting_started.textile +9 -8
- data/guides/source/index.html.erb +154 -0
- data/guides/source/initialization.textile +4138 -0
- data/guides/source/layout.html.erb +15 -7
- data/guides/source/layouts_and_rendering.textile +6 -5
- data/guides/source/nested_model_forms.textile +3 -3
- data/guides/source/performance_testing.textile +4 -4
- data/guides/source/plugins.textile +15 -14
- data/guides/source/rails_on_rack.textile +1 -1
- data/guides/source/routing.textile +379 -490
- data/guides/source/security.textile +5 -5
- data/guides/source/testing.textile +3 -2
- data/lib/rails.rb +7 -2
- data/lib/rails/application.rb +9 -2
- data/lib/rails/application/configuration.rb +19 -10
- data/lib/rails/application/finisher.rb +4 -0
- data/lib/rails/backtrace_cleaner.rb +1 -1
- data/{bin/rails → lib/rails/cli.rb} +0 -0
- data/lib/rails/commands/runner.rb +1 -1
- data/lib/rails/configuration.rb +12 -0
- data/lib/rails/engine.rb +6 -10
- data/lib/rails/engine/configuration.rb +2 -3
- data/lib/rails/generators.rb +1 -6
- data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +0 -7
- data/lib/rails/generators/erb/scaffold/templates/_form.html.erb +10 -1
- data/lib/rails/generators/erb/scaffold/templates/show.html.erb +2 -0
- data/lib/rails/generators/migration.rb +3 -3
- data/lib/rails/generators/rails/app/app_generator.rb +1 -1
- data/lib/rails/generators/rails/app/templates/Gemfile +2 -0
- data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +1 -0
- data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +14 -0
- data/lib/rails/generators/rails/app/templates/config/application.rb +4 -1
- data/lib/rails/generators/rails/app/templates/config/boot.rb +5 -13
- data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +3 -0
- data/lib/rails/generators/rails/app/templates/config/initializers/{cookie_verification_secret.rb.tt → secret_token.rb.tt} +1 -1
- data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +1 -3
- data/lib/rails/generators/rails/app/templates/public/index.html +2 -1
- data/lib/rails/generators/rails/app/templates/public/javascripts/rails.js +41 -32
- data/lib/rails/generators/rails/app/templates/test/{test_helper.rb → test_helper.rb.tt} +2 -0
- data/lib/rails/generators/rails/model/USAGE +15 -0
- data/lib/rails/generators/rails/stylesheets/templates/scaffold.css +3 -8
- data/lib/rails/paths.rb +17 -5
- data/lib/rails/plugin.rb +1 -1
- data/lib/rails/railtie.rb +3 -25
- data/lib/rails/test_unit/testing.rake +11 -7
- data/lib/rails/version.rb +1 -1
- data/lib/rails/webrick_server.rb +2 -2
- metadata +93 -92
- data/guides/source/credits.textile.erb +0 -60
- data/guides/source/index.textile.erb +0 -139
- data/lib/rails/generators/erb/scaffold/templates/layout.html.erb +0 -17
- data/lib/rails/generators/rails/app/templates/app/views/layouts/.empty_directory +0 -0
@@ -1,19 +1,27 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
|
1
4
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
2
5
|
<head>
|
3
6
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
4
7
|
|
5
8
|
<title><%= yield(:page_title) || 'Ruby on Rails guides' %></title>
|
6
9
|
|
7
|
-
<link rel="stylesheet" type="text/css" href="
|
8
|
-
<link rel="stylesheet" type="text/css" href="
|
9
|
-
<link rel="stylesheet" type="text/css" href="
|
10
|
+
<link rel="stylesheet" type="text/css" href="stylesheets/style.css" />
|
11
|
+
<link rel="stylesheet" type="text/css" href="stylesheets/syntax.css" />
|
12
|
+
<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print" />
|
10
13
|
|
11
|
-
<script type="text/javascript" src="
|
12
|
-
<script type="text/javascript" src="
|
13
|
-
<script type="text/javascript" src="
|
14
|
+
<script type="text/javascript" src="javascripts/guides.js"></script>
|
15
|
+
<script type="text/javascript" src="javascripts/code_highlighter.js"></script>
|
16
|
+
<script type="text/javascript" src="javascripts/highlighters.js"></script>
|
14
17
|
|
15
18
|
</head>
|
16
19
|
<body class="guide">
|
20
|
+
<% if @edge %>
|
21
|
+
<div>
|
22
|
+
<img src="images/edge_badge.png" alt="edge-badge" id="edge-badge" />
|
23
|
+
</div>
|
24
|
+
<% end %>
|
17
25
|
<div id="topNav">
|
18
26
|
<div class="wrapper">
|
19
27
|
<strong>More at <a href="http://rubyonrails.org/">rubyonrails.org:</a> </strong>
|
@@ -101,7 +109,7 @@
|
|
101
109
|
<hr class="hide" />
|
102
110
|
<div id="footer">
|
103
111
|
<div class="wrapper">
|
104
|
-
<p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0</a> License</
|
112
|
+
<p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0</a> License</p>
|
105
113
|
<p>"Rails", "Ruby on Rails", and the Rails logo are trademarks of David Heinemeier Hansson. All rights reserved.</p>
|
106
114
|
</div>
|
107
115
|
</div>
|
@@ -510,7 +510,7 @@ def show
|
|
510
510
|
end
|
511
511
|
</ruby>
|
512
512
|
|
513
|
-
Make sure you use +and return+ and not
|
513
|
+
Make sure you use +and return+ and not +&& return+ because while the former will work, the latter will not due to operator precedence in the Ruby Language.
|
514
514
|
|
515
515
|
Note that the implicit render done by ActionController detects if +render+ has been called, and thus avoids this error. Therefore, the following will work without errors:
|
516
516
|
|
@@ -747,7 +747,7 @@ You can even use dynamic paths such as +cache/#{current_site}/main/display+.
|
|
747
747
|
|
748
748
|
h5. Linking to CSS Files with +stylesheet_link_tag+
|
749
749
|
|
750
|
-
The +stylesheet_link_tag+ helper returns an HTML
|
750
|
+
The +stylesheet_link_tag+ helper returns an HTML +<link>+ tag for each source provided. Rails looks in +public/stylesheets+ for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include +public/stylesheets/main.cs+:
|
751
751
|
|
752
752
|
<erb>
|
753
753
|
<%= stylesheet_link_tag "main" %>
|
@@ -1037,7 +1037,7 @@ You can also pass local variables into partials, making them even more powerful
|
|
1037
1037
|
* +_form.html.erb+
|
1038
1038
|
|
1039
1039
|
<erb>
|
1040
|
-
|
1040
|
+
<%= form_for(zone) do |f| %>
|
1041
1041
|
<p>
|
1042
1042
|
<b>Zone name</b><br />
|
1043
1043
|
<%= f.text_field :name %>
|
@@ -1181,11 +1181,11 @@ On pages generated by +NewsController+, you want to hide the top menu and add a
|
|
1181
1181
|
<% content_for :stylesheets do %>
|
1182
1182
|
#top_menu {display: none}
|
1183
1183
|
#right_menu {float: right; background-color: yellow; color: black}
|
1184
|
-
<% end
|
1184
|
+
<% end %>
|
1185
1185
|
<% content_for :content do %>
|
1186
1186
|
<div id="right_menu">Right menu items here</div>
|
1187
1187
|
<%= yield(:news_content) or yield %>
|
1188
|
-
<% end
|
1188
|
+
<% end %>
|
1189
1189
|
<%= render :file => 'layouts/application' %>
|
1190
1190
|
</erb>
|
1191
1191
|
|
@@ -1197,6 +1197,7 @@ h3. Changelog
|
|
1197
1197
|
|
1198
1198
|
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15
|
1199
1199
|
|
1200
|
+
* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
|
1200
1201
|
* January 25, 2010: Rails 3.0 Update by "Mikel Lindsaar":credits.html#raasdnil
|
1201
1202
|
* December 27, 2008: Merge patch from Rodrigo Rosenfeld Rosas covering subtemplates
|
1202
1203
|
* December 27, 2008: Information on new rendering defaults by "Mike Gunderloy":credits.html#mgunderloy
|
@@ -122,7 +122,7 @@ h5. Standard form
|
|
122
122
|
Start out with a regular RESTful form:
|
123
123
|
|
124
124
|
<erb>
|
125
|
-
|
125
|
+
<%= form_for @person do |f| %>
|
126
126
|
<%= f.text_field :name %>
|
127
127
|
<% end %>
|
128
128
|
</erb>
|
@@ -140,7 +140,7 @@ h5. Nested form for a single associated object
|
|
140
140
|
Now add a nested form for the +address+ association:
|
141
141
|
|
142
142
|
<erb>
|
143
|
-
|
143
|
+
<%= form_for @person do |f| %>
|
144
144
|
<%= f.text_field :name %>
|
145
145
|
|
146
146
|
<% f.fields_for :address do |af| %>
|
@@ -181,7 +181,7 @@ h5. Nested form for a collection of associated objects
|
|
181
181
|
The form code for an association collection is pretty similar to that of a single associated object:
|
182
182
|
|
183
183
|
<erb>
|
184
|
-
|
184
|
+
<%= form_for @person do |f| %>
|
185
185
|
<%= f.text_field :name %>
|
186
186
|
|
187
187
|
<% f.fields_for :projects do |pf| %>
|
@@ -213,11 +213,11 @@ h4. Understanding the Output
|
|
213
213
|
|
214
214
|
Performance tests generate different outputs inside +tmp/performance+ directory depending on their mode and metric.
|
215
215
|
|
216
|
-
h5. Benchmarking
|
216
|
+
h5(#output-benchmarking). Benchmarking
|
217
217
|
|
218
218
|
In benchmarking mode, performance tests generate two types of outputs:
|
219
219
|
|
220
|
-
h6. Command Line
|
220
|
+
h6(#output-command-line). Command Line
|
221
221
|
|
222
222
|
This is the primary form of output in benchmarking mode. Example:
|
223
223
|
|
@@ -258,7 +258,7 @@ measurement,created_at,app,rails,ruby,platform
|
|
258
258
|
0.00771250000000012,2009-01-09T15:46:03Z,,2.3.0.master.859e150,ruby-1.8.6.110,i686-darwin9.0.0
|
259
259
|
</shell>
|
260
260
|
|
261
|
-
h5. Profiling
|
261
|
+
h5(#output-profiling). Profiling
|
262
262
|
|
263
263
|
In profiling mode, you can choose from four types of output.
|
264
264
|
|
@@ -330,7 +330,7 @@ h5. Apply the Patch
|
|
330
330
|
|
331
331
|
h5. Configure and Install
|
332
332
|
|
333
|
-
The following will install ruby in your home directory's +/rubygc+ directory. Make sure to replace
|
333
|
+
The following will install ruby in your home directory's +/rubygc+ directory. Make sure to replace +<homedir>+ with a full patch to your actual home directory.
|
334
334
|
|
335
335
|
<shell>
|
336
336
|
[lifo@null ruby-version]$ ./configure --prefix=/<homedir>/rubygc
|
@@ -35,14 +35,14 @@ h4. Create the Basic Application
|
|
35
35
|
|
36
36
|
The examples in this guide require that you have a working rails application. To create a simple rails app execute:
|
37
37
|
|
38
|
-
<
|
38
|
+
<shell>
|
39
39
|
gem install rails
|
40
40
|
rails yaffle_guide
|
41
41
|
cd yaffle_guide
|
42
42
|
rails generate scaffold bird name:string
|
43
43
|
rake db:migrate
|
44
44
|
rails server
|
45
|
-
</
|
45
|
+
</shell>
|
46
46
|
|
47
47
|
Then navigate to http://localhost:3000/birds. Make sure you have a functioning rails app before continuing.
|
48
48
|
|
@@ -56,22 +56,22 @@ Rails ships with a plugin generator which creates a basic plugin skeleton. Pass
|
|
56
56
|
This creates a plugin in 'vendor/plugins' including an 'init.rb' and 'README' as well as standard 'lib', 'task', and 'test' directories.
|
57
57
|
|
58
58
|
Examples:
|
59
|
-
<
|
59
|
+
<shell>
|
60
60
|
rails generate plugin yaffle
|
61
61
|
rails generate plugin yaffle --with-generator
|
62
|
-
</
|
62
|
+
</shell>
|
63
63
|
|
64
64
|
To get more detailed help on the plugin generator, type +rails generate plugin+.
|
65
65
|
|
66
66
|
Later on this guide will describe how to work with generators, so go ahead and generate your plugin with the +--with-generator+ option now:
|
67
67
|
|
68
|
-
<
|
68
|
+
<shell>
|
69
69
|
rails generate plugin yaffle --with-generator
|
70
|
-
</
|
70
|
+
</shell>
|
71
71
|
|
72
72
|
You should see the following output:
|
73
73
|
|
74
|
-
<
|
74
|
+
<shell>
|
75
75
|
create vendor/plugins/yaffle/lib
|
76
76
|
create vendor/plugins/yaffle/tasks
|
77
77
|
create vendor/plugins/yaffle/test
|
@@ -89,20 +89,20 @@ create vendor/plugins/yaffle/generators/yaffle
|
|
89
89
|
create vendor/plugins/yaffle/generators/yaffle/templates
|
90
90
|
create vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb
|
91
91
|
create vendor/plugins/yaffle/generators/yaffle/USAGE
|
92
|
-
</
|
92
|
+
</shell>
|
93
93
|
|
94
94
|
h4. Organize Your Files
|
95
95
|
|
96
96
|
To make it easy to organize your files and to make the plugin more compatible with GemPlugins, start out by altering your file system to look like this:
|
97
97
|
|
98
|
-
<
|
98
|
+
<shell>
|
99
99
|
|-- lib
|
100
100
|
| |-- yaffle
|
101
101
|
| `-- yaffle.rb
|
102
102
|
`-- rails
|
103
103
|
|
|
104
104
|
`-- init.rb
|
105
|
-
</
|
105
|
+
</shell>
|
106
106
|
|
107
107
|
*vendor/plugins/yaffle/init.rb*
|
108
108
|
|
@@ -124,7 +124,7 @@ h4. Test Setup
|
|
124
124
|
|
125
125
|
*vendor/plugins/yaffle/test/database.yml:*
|
126
126
|
|
127
|
-
<
|
127
|
+
<yaml>
|
128
128
|
sqlite:
|
129
129
|
:adapter: sqlite
|
130
130
|
:dbfile: vendor/plugins/yaffle/test/yaffle_plugin.sqlite.db
|
@@ -146,7 +146,7 @@ mysql:
|
|
146
146
|
:username: root
|
147
147
|
:password: password
|
148
148
|
:database: yaffle_plugin_test
|
149
|
-
</
|
149
|
+
</yaml>
|
150
150
|
|
151
151
|
For this guide you'll need 2 tables/models, Hickwalls and Wickwalls, so add the following:
|
152
152
|
|
@@ -239,10 +239,10 @@ end
|
|
239
239
|
|
240
240
|
To run this, go to the plugin directory and run +rake+:
|
241
241
|
|
242
|
-
<
|
242
|
+
<shell>
|
243
243
|
cd vendor/plugins/yaffle
|
244
244
|
rake
|
245
|
-
</
|
245
|
+
</shell>
|
246
246
|
|
247
247
|
You should see output like:
|
248
248
|
|
@@ -1511,4 +1511,5 @@ h3. Changelog
|
|
1511
1511
|
|
1512
1512
|
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/32-update-plugins-guide
|
1513
1513
|
|
1514
|
+
* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
|
1514
1515
|
* November 17, 2008: Major revision by Jeff Dean
|
@@ -28,7 +28,7 @@ h3. Rails on Rack
|
|
28
28
|
|
29
29
|
h4. Rails Application's Rack Object
|
30
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
|
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.
|
32
32
|
|
33
33
|
h4. +rails server+
|
34
34
|
|
@@ -2,180 +2,111 @@ h2. Rails Routing from the Outside In
|
|
2
2
|
|
3
3
|
This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to:
|
4
4
|
|
5
|
-
* Understand the
|
6
|
-
*
|
7
|
-
*
|
8
|
-
*
|
5
|
+
* Understand the code in +routes.rb+
|
6
|
+
* Construct your own routes, using either the preferred resourceful style or with the @match@ method
|
7
|
+
* Identify what parameters to expect an action to receive
|
8
|
+
* Automatically create URLs using route helpers
|
9
|
+
* Use advanced techniques such as constraints and Rack endpoints
|
9
10
|
|
10
11
|
endprologue.
|
11
12
|
|
12
|
-
h3. The
|
13
|
+
h3. The Purpose of the Rails Router
|
13
14
|
|
14
|
-
Rails
|
15
|
+
The Rails router recognizes URLs and dispatches them to a controller's action. It can also generate URLs, avoiding the need to hardcode URL strings in your views.
|
15
16
|
|
16
17
|
h4. Connecting URLs to Code
|
17
18
|
|
18
|
-
When your Rails application receives an incoming
|
19
|
+
When your Rails application receives an incoming request
|
19
20
|
|
20
|
-
<
|
21
|
+
<plain>
|
21
22
|
GET /patients/17
|
22
|
-
</
|
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 Restful resource for this style of translation 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 +ApplicationName::Application.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
|
23
|
+
</plain>
|
55
24
|
|
56
|
-
|
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, and then proceeds to the next. 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 with a single declaration. A RESTful route looks like this:
|
25
|
+
it asks the router to match it to a controller action. If the first matching route is
|
63
26
|
|
64
27
|
<ruby>
|
65
|
-
|
28
|
+
match "/patients/:id" => "patients#show"
|
66
29
|
</ruby>
|
67
30
|
|
68
|
-
|
69
|
-
|
70
|
-
Named routes give you very readable links in your code, as well as handling incoming requests. Here's a typical named route:
|
31
|
+
the request is dispatched to the +patients+ controller's +show+ action with <tt>{ :id => "17" }</tt> in +params+.
|
71
32
|
|
72
|
-
|
73
|
-
match 'login' => 'sessions#new', :as => 'login'
|
74
|
-
</ruby>
|
33
|
+
h4. Generating URLs from Code
|
75
34
|
|
76
|
-
|
35
|
+
You can also generate routes. If your application contains this code:
|
77
36
|
|
78
37
|
<ruby>
|
79
|
-
|
38
|
+
@patient = Patient.find(17)
|
80
39
|
</ruby>
|
81
40
|
|
82
|
-
|
41
|
+
<erb>
|
42
|
+
<%= link_to "Patient Record", patients_path(@patient.id) %>
|
43
|
+
</erb>
|
83
44
|
|
84
|
-
|
45
|
+
The router will generate the path +/patients/17+. This reduces the brittleness of your view and makes your code easier to understand.
|
85
46
|
|
86
|
-
|
47
|
+
h3. Resource Routing: the Rails Default
|
87
48
|
|
88
|
-
|
89
|
-
resources :assemblies do
|
90
|
-
resources :parts
|
91
|
-
end
|
92
|
-
</ruby>
|
49
|
+
Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+ actions, a resourceful route declares them in a single line of code.
|
93
50
|
|
94
|
-
h4.
|
51
|
+
h4. Resources on the Web
|
95
52
|
|
96
|
-
|
53
|
+
Browsers request pages from Rails by making a request for a URL using a specific HTTP method, such as +GET+, +POST+, +PUT+ and +DELETE+. Each method is a request to perform an operation on the resource. A resource route maps a number of related request to the actions in a single controller.
|
97
54
|
|
98
|
-
|
99
|
-
match 'parts/:number' => 'inventory#show'
|
100
|
-
</ruby>
|
55
|
+
When your Rails application receives an incoming request for
|
101
56
|
|
102
|
-
|
57
|
+
<plain>
|
58
|
+
DELETE /photos/17
|
59
|
+
</plain>
|
103
60
|
|
104
|
-
|
61
|
+
it asks the router to map it to a controller action. If the first matching route is
|
105
62
|
|
106
63
|
<ruby>
|
107
|
-
|
64
|
+
resources :photos
|
108
65
|
</ruby>
|
109
66
|
|
110
|
-
|
111
|
-
|
112
|
-
h3. RESTful Routing: the Rails Default
|
113
|
-
|
114
|
-
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.
|
115
|
-
|
116
|
-
h4. What is REST?
|
117
|
-
|
118
|
-
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:
|
119
|
-
|
120
|
-
* Using resource identifiers (which, for the purposes of discussion, you can think of as URLs) to represent resources
|
121
|
-
* Transferring representations of the state of that resource between system components.
|
122
|
-
|
123
|
-
For example, to a Rails application a request such as this:
|
124
|
-
|
125
|
-
<pre>
|
126
|
-
DELETE /photos/17
|
127
|
-
</pre>
|
128
|
-
|
129
|
-
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.
|
67
|
+
Rails would dispatch that request to the +destroy+ method on the +photos+ controller with <tt>{ :id => "17" }</tt> in +params+.
|
130
68
|
|
131
69
|
h4. CRUD, Verbs, and Actions
|
132
70
|
|
133
|
-
In Rails, a
|
71
|
+
In Rails, a resourceful route provides a mapping between HTTP verbs and URLs and controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as
|
134
72
|
|
135
73
|
<ruby>
|
136
74
|
resources :photos
|
137
75
|
</ruby>
|
138
76
|
|
139
|
-
creates seven different routes in your application:
|
140
|
-
|
141
|
-
|_.HTTP verb|_.URL |_.controller|_.action |_.used for|
|
142
|
-
|GET |/photos |Photos |index |display a list of all photos|
|
143
|
-
|GET |/photos/new |Photos |new |return an HTML form for creating a new photo|
|
144
|
-
|POST |/photos |Photos |create |create a new photo|
|
145
|
-
|GET |/photos/1 |Photos |show |display a specific photo|
|
146
|
-
|GET |/photos/1/edit |Photos |edit |return an HTML form for editing a photo|
|
147
|
-
|PUT |/photos/1 |Photos |update |update a specific photo|
|
148
|
-
|DELETE |/photos/1 |Photos |destroy |delete a specific photo|
|
77
|
+
creates seven different routes in your application, all mapping to the +Photos+ controller:
|
149
78
|
|
150
|
-
|
79
|
+
|_. Verb |_.URL |_.action |_.used for|
|
80
|
+
|GET |/photos |index |display a list of all photos|
|
81
|
+
|GET |/photos/new |new |return an HTML form for creating a new photo|
|
82
|
+
|POST |/photos |create |create a new photo|
|
83
|
+
|GET |/photos/:id |show |display a specific photo|
|
84
|
+
|GET |/photos/:id/edit |edit |return an HTML form for editing a photo|
|
85
|
+
|PUT |/photos/:id |update |update a specific photo|
|
86
|
+
|DELETE |/photos/:id |destroy |delete a specific photo|
|
151
87
|
|
152
88
|
h4. URLs and Paths
|
153
89
|
|
154
|
-
Creating a
|
90
|
+
Creating a resourceful route will also expose a number of helpers to the controllers in your application. In the case of +resources :photos+:
|
155
91
|
|
156
|
-
* +
|
157
|
-
* +
|
158
|
-
* +
|
159
|
-
* +
|
92
|
+
* +photos_path+ returns +/photos+
|
93
|
+
* +new_photo_path+ returns +/photos/new+
|
94
|
+
* +edit_photo_path+ returns +/photos/edit+
|
95
|
+
* +photo_path(id)+ returns +/photos/:id+ (for instance, +photo_path(10)+ returns +/photos/10+)
|
160
96
|
|
161
|
-
|
97
|
+
Each of these helpers has a corresponding +_url+ helper (such as +photos_url+) which returns the same path prefixed with the current host, port and path prefix.
|
162
98
|
|
163
|
-
|
164
|
-
|
165
|
-
<ruby>
|
166
|
-
photos_url # => "http://www.example.com/photos"
|
167
|
-
photos_path # => "/photos"
|
168
|
-
</ruby>
|
99
|
+
NOTE: Because the router uses the HTTP verb and URL to match inbound requests, four URLs map to seven different actions.
|
169
100
|
|
170
101
|
h4. Defining Multiple Resources at the Same Time
|
171
102
|
|
172
|
-
If you need to create routes for more than one
|
103
|
+
If you need to create routes for more than one resource, you can save a bit of typing by defining them all with a single call to +resources+:
|
173
104
|
|
174
105
|
<ruby>
|
175
106
|
resources :photos, :books, :videos
|
176
107
|
</ruby>
|
177
108
|
|
178
|
-
This
|
109
|
+
This works exactly the same as
|
179
110
|
|
180
111
|
<ruby>
|
181
112
|
resources :photos
|
@@ -185,659 +116,615 @@ resources :videos
|
|
185
116
|
|
186
117
|
h4. Singular Resources
|
187
118
|
|
188
|
-
|
119
|
+
Sometimes, you have a resource that clients always look up without referencing an ID. A common example, +/profile+ always shows the profile of the currently logged in user. In this case, you can use a singular resource to map +/profile+ (rather than +/profile/:id+) to the +show+ action.
|
189
120
|
|
190
121
|
<ruby>
|
191
122
|
resource :geocoder
|
192
123
|
</ruby>
|
193
124
|
|
194
|
-
creates six different routes in your application:
|
195
|
-
|
196
|
-
|_.HTTP verb|_.URL |_.controller|_.action |_.used for|
|
197
|
-
|GET |/geocoder/new |Geocoders |new |return an HTML form for creating the new geocoder|
|
198
|
-
|POST |/geocoder |Geocoders |create |create the new geocoder|
|
199
|
-
|GET |/geocoder |Geocoders |show |display the one and only geocoder resource|
|
200
|
-
|GET |/geocoder/edit |Geocoders |edit |return an HTML form for editing the geocoder|
|
201
|
-
|PUT |/geocoder |Geocoders |update |update the one and only geocoder resource|
|
202
|
-
|DELETE |/geocoder |Geocoders |destroy |delete the geocoder resource|
|
203
|
-
|
204
|
-
NOTE: Even though the name of the resource is singular in +routes.rb+, the matching controller is still plural.
|
125
|
+
creates six different routes in your application, all mapping to the +Geocoders+ controller:
|
205
126
|
|
206
|
-
|
127
|
+
|_. Verb |_.URL |_.action |_.used for|
|
128
|
+
|GET |/geocoder/new |new |return an HTML form for creating the geocoder|
|
129
|
+
|POST |/geocoder |create |create the new geocoder|
|
130
|
+
|GET |/geocoder |show |display the one and only geocoder resource|
|
131
|
+
|GET |/geocoder/edit |edit |return an HTML form for editing the geocoder|
|
132
|
+
|PUT |/geocoder |update |update the one and only geocoder resource|
|
133
|
+
|DELETE |/geocoder |destroy |delete the geocoder resource|
|
207
134
|
|
208
|
-
|
209
|
-
* +edit_geocoder_url+ and +edit_geocoder_path+ map to the path for the edit action
|
210
|
-
* +geocoder_url+ and +geocoder_path+ map to the path for the create, show, update, and destroy actions
|
135
|
+
NOTE: Because you might want to use the same controller for a singular route (+/account+) and a plural route (+/accounts/45+), singular resources map to plural controllers.
|
211
136
|
|
212
|
-
|
137
|
+
A singular resourceful route generates these helpers:
|
213
138
|
|
214
|
-
|
139
|
+
* +new_geocoder_path+ returns +/geocoder/new+
|
140
|
+
* +edit_geocoder_path+ returns +/geocoder/edit+
|
141
|
+
* +geocoder_path+ returns +/geocoder+
|
215
142
|
|
216
|
-
|
217
|
-
* +:singular+
|
218
|
-
* +:requirements+
|
219
|
-
* +:conditions+
|
220
|
-
* +:as+
|
221
|
-
* +:path_names+
|
222
|
-
* +:only+
|
223
|
-
* +:except+
|
143
|
+
As with plural resources, the same helpers ending in +_url+ will also include the host, port and path prefix.
|
224
144
|
|
225
|
-
|
226
|
-
|
227
|
-
h5. Using +:controller+
|
145
|
+
h4. Controller Namespaces and Routing
|
228
146
|
|
229
|
-
|
147
|
+
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an +Admin::+ namespace. You would place these controllers under the +app/controllers/admin+ directory, and you can group them together in your router:
|
230
148
|
|
231
149
|
<ruby>
|
232
|
-
|
150
|
+
namespace "admin" do
|
151
|
+
resources :posts, :comments
|
152
|
+
end
|
233
153
|
</ruby>
|
234
154
|
|
235
|
-
will
|
155
|
+
This will create a number of routes for each of the +posts+ and +comments+ controller. For +Admin::PostsController+, Rails will create:
|
236
156
|
|
237
|
-
|_.
|
238
|
-
|GET
|
239
|
-
|GET
|
240
|
-
|POST
|
241
|
-
|GET
|
242
|
-
|GET
|
243
|
-
|PUT
|
244
|
-
|DELETE
|
157
|
+
|_. Verb |_.URL |_.action |_. helper |
|
158
|
+
|GET |/admin/photos |index | admin_photos_path |
|
159
|
+
|GET |/admin/photos/new |new | new_admin_photos_path |
|
160
|
+
|POST |/admin/photos |create | admin_photos_path |
|
161
|
+
|GET |/admin/photos/1 |show | admin_photo_path(id) |
|
162
|
+
|GET |/admin/photos/1/edit |edit | edit_admin_photo_path(id) |
|
163
|
+
|PUT |/admin/photos/1 |update | admin_photo_path(id) |
|
164
|
+
|DELETE |/admin/photos/1 |destroy | admin_photo_path(id) |
|
245
165
|
|
246
|
-
|
247
|
-
|
248
|
-
h4. Controller Namespaces and Routing
|
249
|
-
|
250
|
-
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:
|
166
|
+
If you want to route +/photos+ (without the prefix +/admin+) to +Admin::PostsController+, you could use
|
251
167
|
|
252
168
|
<ruby>
|
253
|
-
|
169
|
+
scope :module => "admin" do
|
170
|
+
resources :posts, :comments
|
171
|
+
end
|
254
172
|
</ruby>
|
255
173
|
|
256
|
-
|
257
|
-
|
258
|
-
TIP: If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: +<%= link_to "show", {:controller => "/photos", :action => "show"} %>+
|
259
|
-
|
260
|
-
You can also specify a controller namespace with the +:namespace+ option instead of a path:
|
174
|
+
or, for a single case
|
261
175
|
|
262
176
|
<ruby>
|
263
|
-
resources :
|
177
|
+
resources :posts, :module => "admin"
|
264
178
|
</ruby>
|
265
179
|
|
266
|
-
|
180
|
+
If you want to route +/admin/photos+ to +PostsController+ (without the +Admin::+ module prefix), you could use
|
267
181
|
|
268
182
|
<ruby>
|
269
|
-
|
270
|
-
resources :
|
183
|
+
scope "/admin" do
|
184
|
+
resources :posts, :comments
|
271
185
|
end
|
272
186
|
</ruby>
|
273
187
|
|
274
|
-
|
275
|
-
|
276
|
-
The difference between generating routes through +namespace+ and the +:controller+ key is that the +namespace+ will add +admin+ to the generated helpers as well, so the above route generates +admin_photos_path+.
|
277
|
-
|
278
|
-
h5. Using +:singular+
|
279
|
-
|
280
|
-
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:
|
188
|
+
or, for a single case
|
281
189
|
|
282
190
|
<ruby>
|
283
|
-
resources :
|
191
|
+
resources :posts, :path => "/admin"
|
284
192
|
</ruby>
|
285
193
|
|
286
|
-
|
287
|
-
|
288
|
-
h5. Using +:requirements+
|
194
|
+
In each of these cases, the named routes remain the same as if you did not use +scope+. In the last case, the following URLs map to +PostsController+:
|
289
195
|
|
290
|
-
|
196
|
+
|_. Verb |_.URL |_.action |_. helper |
|
197
|
+
|GET |photos |index | photos_path |
|
198
|
+
|GET |photos/new |new | photos_path |
|
199
|
+
|POST |photos |create | photos_path |
|
200
|
+
|GET |photos/1 |show | photo_path(id) |
|
201
|
+
|GET |photos/1/edit |edit | dmin_photo_path(id) |
|
202
|
+
|PUT |photos/1 |update | photo_path(id) |
|
203
|
+
|DELETE |photos/1 |destroy | photo_path(id) |
|
291
204
|
|
292
|
-
|
293
|
-
resources :photos, :requirements => {:id => /[A-Z][A-Z][0-9]+/}
|
294
|
-
</ruby>
|
295
|
-
|
296
|
-
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.
|
205
|
+
h4. Nested Resources
|
297
206
|
|
298
|
-
|
207
|
+
It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
|
299
208
|
|
300
|
-
|
209
|
+
<ruby>
|
210
|
+
class Magazine < ActiveRecord::Base
|
211
|
+
has_many :ads
|
212
|
+
end
|
301
213
|
|
302
|
-
|
214
|
+
class Ad < ActiveRecord::Base
|
215
|
+
belongs_to :magazine
|
216
|
+
end
|
217
|
+
</ruby>
|
303
218
|
|
304
|
-
|
219
|
+
Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration:
|
305
220
|
|
306
221
|
<ruby>
|
307
|
-
resources :
|
222
|
+
resources :magazines do
|
223
|
+
resources :ads
|
224
|
+
end
|
308
225
|
</ruby>
|
309
226
|
|
310
|
-
|
227
|
+
In addition to the routes for magazines, this declaration will also route ads to an +AdsController+. The ad URLs require a magazine:
|
311
228
|
|
312
|
-
|_.
|
313
|
-
|GET
|
314
|
-
|GET
|
315
|
-
|POST
|
316
|
-
|GET
|
317
|
-
|GET
|
318
|
-
|PUT
|
319
|
-
|DELETE
|
229
|
+
|_.Verb |_.URL |_.action |_.used for|
|
230
|
+
|GET |/magazines/1/ads |index |display a list of all ads for a specific magazine|
|
231
|
+
|GET |/magazines/1/ads/new |new |return an HTML form for creating a new ad belonging to a specific magazine|
|
232
|
+
|POST |/magazines/1/ads |create |create a new ad belonging to a specific magazine|
|
233
|
+
|GET |/magazines/1/ads/1 |show |display a specific ad belonging to a specific magazine|
|
234
|
+
|GET |/magazines/1/ads/1/edit |edit |return an HTML form for editing an ad belonging to a specific magazine|
|
235
|
+
|PUT |/magazines/1/ads/1 |update |update a specific ad belonging to a specific magazine|
|
236
|
+
|DELETE |/magazines/1/ads/1 |destroy |delete a specific ad belonging to a specific magazine|
|
320
237
|
|
321
|
-
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.
|
322
238
|
|
323
|
-
|
239
|
+
This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+. These helpers take an instance of Magazine as the first parameter (+magazine_ads_url(@magazine)+).
|
324
240
|
|
325
|
-
|
241
|
+
h5. Limits to Nesting
|
242
|
+
|
243
|
+
You can nest resources within other nested resources if you like. For example:
|
326
244
|
|
327
245
|
<ruby>
|
328
|
-
resources :
|
246
|
+
resources :publishers do
|
247
|
+
resources :magazines do
|
248
|
+
resources :photos
|
249
|
+
end
|
250
|
+
end
|
329
251
|
</ruby>
|
330
252
|
|
331
|
-
|
253
|
+
Deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize URLs such as
|
332
254
|
|
333
255
|
<pre>
|
334
|
-
/photos/
|
335
|
-
/photos/1/change
|
256
|
+
/publishers/1/magazines/2/photos/3
|
336
257
|
</pre>
|
337
258
|
|
338
|
-
|
339
|
-
|
340
|
-
TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can set a default in your environment:
|
259
|
+
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:
|
341
260
|
|
342
|
-
|
343
|
-
config.action_controller.resources_path_names = { :new => 'make', :edit => 'change' }
|
344
|
-
</ruby>
|
261
|
+
TIP: _Resources should never be nested more than 1 level deep._
|
345
262
|
|
346
|
-
|
263
|
+
h4. Creating URLs From Objects
|
347
264
|
|
348
|
-
|
265
|
+
In addition to using the routing helpers, Rails can also create URLs from an array of parameters. For example, suppose you have this set of routes:
|
349
266
|
|
350
267
|
<ruby>
|
351
|
-
resources :
|
268
|
+
resources :magazines do
|
269
|
+
resources :ads
|
270
|
+
end
|
352
271
|
</ruby>
|
353
272
|
|
354
|
-
|
273
|
+
When using +magazine_ad_path+, you can pass in instances of +Magazine+ and +Ad+ instead of the numeric IDs.
|
355
274
|
|
356
|
-
<
|
357
|
-
|
358
|
-
|
359
|
-
</pre>
|
360
|
-
|
361
|
-
NOTE: In most cases, it's simpler to recognize URLs of this sort by creating nested resources, as discussed in the next section.
|
275
|
+
<erb>
|
276
|
+
<%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %>
|
277
|
+
</erb>
|
362
278
|
|
363
|
-
|
279
|
+
You can also use +url_for+ with a set of objects, and Rails will automatically determine which route you want:
|
364
280
|
|
365
|
-
|
281
|
+
<erb>
|
282
|
+
<%= link_to "Ad details", url_for(@magazine, @ad) %>
|
283
|
+
</erb>
|
366
284
|
|
367
|
-
|
285
|
+
In this case, Rails will see that +@magazine+ is a +Magazine+ and +@ad+ is an +Ad+ and will therefore use the +magazine_ad_path+ helper. In helpers like +link_to+, you can specify just the object in place of the full +url_for+ call:
|
368
286
|
|
369
|
-
<
|
370
|
-
|
371
|
-
|
372
|
-
resources :photos, :path_prefix => '/agencies/:agency_id',
|
373
|
-
:name_prefix => 'agency_'
|
374
|
-
</ruby>
|
287
|
+
<erb>
|
288
|
+
<%= link_to "Ad details", [@magazine, @ad] %>
|
289
|
+
</erb>
|
375
290
|
|
376
|
-
|
291
|
+
If you wanted to link to just a magazine, you could leave out the +Array+:
|
377
292
|
|
378
|
-
|
293
|
+
<erb>
|
294
|
+
<%= link_to "Magazine details", @magazine %>
|
295
|
+
</erb>
|
379
296
|
|
380
|
-
|
297
|
+
This allows you to treat instances of your models as URLs, and is a key advantage to using the resourceful style.
|
381
298
|
|
382
|
-
|
299
|
+
h4. Adding More RESTful Actions
|
383
300
|
|
384
|
-
|
385
|
-
resources :photos, :only => [:index, :show]
|
386
|
-
</ruby>
|
301
|
+
You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional routes that apply to the collection or individual members of the collection.
|
387
302
|
|
388
|
-
|
303
|
+
h5. Adding Member Routes
|
389
304
|
|
390
|
-
|
305
|
+
To add a member route, just add +member+ block into resource block:
|
391
306
|
|
392
307
|
<ruby>
|
393
|
-
resources :photos
|
308
|
+
resources :photos do
|
309
|
+
member do
|
310
|
+
get :preview
|
311
|
+
end
|
312
|
+
end
|
394
313
|
</ruby>
|
395
314
|
|
396
|
-
|
315
|
+
This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers.
|
397
316
|
|
398
|
-
|
317
|
+
Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also passing +:on+ to a route.
|
399
318
|
|
400
|
-
|
319
|
+
<ruby>
|
320
|
+
resources :photos do
|
321
|
+
get :preview, :on => :member
|
322
|
+
end
|
323
|
+
</ruby>
|
401
324
|
|
402
|
-
|
325
|
+
h5. Adding Collection Routes
|
403
326
|
|
404
|
-
|
327
|
+
To add a route to the collection:
|
405
328
|
|
406
329
|
<ruby>
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
class Ad < ActiveRecord::Base
|
412
|
-
belongs_to :magazine
|
330
|
+
resources :photos do
|
331
|
+
collection do
|
332
|
+
get :search
|
333
|
+
end
|
413
334
|
end
|
414
335
|
</ruby>
|
415
336
|
|
416
|
-
|
337
|
+
This will enable Rails to recognize URLs such as +/photos/search+ with GET, and route to the +search+ action of +PhotosController+. It will also create the +search_photos_url+ and +search_photos_path+ route helpers.
|
338
|
+
|
339
|
+
Just as with member routes, you can pass +:on+ to a route.
|
417
340
|
|
418
341
|
<ruby>
|
419
|
-
resources :
|
420
|
-
|
342
|
+
resources :photos do
|
343
|
+
get :search, :on => :collection
|
421
344
|
end
|
422
345
|
</ruby>
|
423
346
|
|
424
|
-
|
425
|
-
|
426
|
-
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:
|
347
|
+
h5. A Note of Caution
|
427
348
|
|
428
|
-
|
429
|
-
|GET |/magazines/1/ads |Ads |index |display a list of all ads for a specific magazine|
|
430
|
-
|GET |/magazines/1/ads/new |Ads |new |return an HTML form for creating a new ad belonging to a specific magazine|
|
431
|
-
|POST |/magazines/1/ads |Ads |create |create a new ad belonging to a specific magazine|
|
432
|
-
|GET |/magazines/1/ads/1 |Ads |show |display a specific ad belonging to a specific magazine|
|
433
|
-
|GET |/magazines/1/ads/1/edit |Ads |edit |return an HTML form for editing an ad belonging to a specific magazine|
|
434
|
-
|PUT |/magazines/1/ads/1 |Ads |update |update a specific ad belonging to a specific magazine|
|
435
|
-
|DELETE |/magazines/1/ads/1 |Ads |destroy |delete a specific ad belonging to a specific magazine|
|
349
|
+
If you find yourself adding many extra actions to a resourceful route, it's time to stop and ask yourself whether you're disguising the presence of another resource.
|
436
350
|
|
351
|
+
h3. Non-Resourceful Routes
|
437
352
|
|
438
|
-
|
353
|
+
In addition to resource routing, Rails has powerful support for routing arbitrary URLs to actions. Here, you don't get groups of routes automatically generated by resourceful routing. Instead, you set up each route within your application separately.
|
439
354
|
|
440
|
-
|
355
|
+
While you should usually use resourceful routing, there are still many places where the simpler routing is more appropriate. There's no need to try to shoehorn every last piece of your application into a resourceful framework if that's not a good fit.
|
441
356
|
|
442
|
-
|
357
|
+
In particular, simple routing makes it very easy to map legacy URLs to new Rails actions.
|
443
358
|
|
444
|
-
|
445
|
-
resources :magazines do
|
446
|
-
resources :ads, :name_prefix => 'periodical'
|
447
|
-
end
|
448
|
-
</ruby>
|
359
|
+
h4. Bound Parameters
|
449
360
|
|
450
|
-
|
361
|
+
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:
|
451
362
|
|
452
363
|
<ruby>
|
453
|
-
|
454
|
-
resources :ads, :name_prefix => nil
|
455
|
-
end
|
364
|
+
match ':controller(/:action(/:id))'
|
456
365
|
</ruby>
|
457
366
|
|
458
|
-
|
367
|
+
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 +PhotosController+, and to make the final parameter +"1"+ available as +params[:id]+. This route will also route the incoming request of +/photos+ to +PhotosController+, since +:action+ and +:id+ are optional parameters, denoted by parentheses.
|
459
368
|
|
460
|
-
|
461
|
-
ads_url(@magazine)
|
462
|
-
edit_ad_path(@magazine, @ad)
|
463
|
-
</ruby>
|
464
|
-
|
465
|
-
h5. Using +:has_one+ and +:has_many+
|
369
|
+
h4. Dynamic Segments
|
466
370
|
|
467
|
-
|
371
|
+
You can set up as many dynamic segments within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the action as part of +params+. If you set up this route:
|
468
372
|
|
469
373
|
<ruby>
|
470
|
-
|
374
|
+
match ':controller/:action/:id/:user_id'
|
471
375
|
</ruby>
|
472
376
|
|
473
|
-
|
377
|
+
An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of the +PhotosController+. +params[:id]+ will be +"1"+, and +params[:user_id]+ will be +"2"+.
|
474
378
|
|
475
|
-
|
476
|
-
resources :photos do
|
477
|
-
resource :photographer
|
478
|
-
resources :publications
|
479
|
-
resources :versions
|
480
|
-
end
|
481
|
-
</ruby>
|
482
|
-
|
483
|
-
h5. Limits to Nesting
|
379
|
+
h4. Static Segments
|
484
380
|
|
485
|
-
You can
|
381
|
+
You can specify static segments when creating a route.
|
486
382
|
|
487
383
|
<ruby>
|
488
|
-
|
489
|
-
resources :magazines do
|
490
|
-
resources :photos
|
491
|
-
end
|
492
|
-
end
|
384
|
+
match ':controller/:action/:id/with_user/:user_id'
|
493
385
|
</ruby>
|
494
386
|
|
495
|
-
|
496
|
-
|
497
|
-
<pre>
|
498
|
-
/publishers/1/magazines/2/photos/3
|
499
|
-
</pre>
|
500
|
-
|
501
|
-
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:
|
502
|
-
|
503
|
-
TIP: _Resources should never be nested more than 1 level deep._
|
387
|
+
This route would respond to URLs such as +/photos/show/1/with_user/2+. In this case, +params+ would be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
|
504
388
|
|
505
|
-
|
389
|
+
h4. The Query String
|
506
390
|
|
507
|
-
The
|
391
|
+
The +params+ will also include any parameters from the query string. For example, with this route:
|
508
392
|
|
509
393
|
<ruby>
|
510
|
-
|
511
|
-
resources :magazines do
|
512
|
-
resources :photos
|
513
|
-
end
|
514
|
-
end
|
394
|
+
match ':controller/:action/:id
|
515
395
|
</ruby>
|
516
396
|
|
517
|
-
|
397
|
+
An incoming URL of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params+ will be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
|
518
398
|
|
519
|
-
|
520
|
-
/publishers/1 ==> publisher_path(1)
|
521
|
-
/publishers/1/magazines ==> publisher_magazines_path(1)
|
522
|
-
/magazines/2 ==> magazine_path(2)
|
523
|
-
/magazines/2/photos ==> magazines_photos_path(2)
|
524
|
-
/photos/3 ==> photo_path(3)
|
525
|
-
</pre>
|
399
|
+
h4. Defining Defaults
|
526
400
|
|
527
|
-
|
401
|
+
You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply them as defaults:
|
528
402
|
|
529
403
|
<ruby>
|
530
|
-
|
404
|
+
match 'photos/:id' => 'photos#show'
|
531
405
|
</ruby>
|
532
406
|
|
533
|
-
|
407
|
+
With this route, Rails will match an incoming URL of +/photos/12+ to the +show+ action of +PhotosController+.
|
534
408
|
|
535
|
-
|
409
|
+
You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that you do not specify as dynamic segments. For example:
|
536
410
|
|
537
411
|
<ruby>
|
538
|
-
|
539
|
-
resources :ads
|
540
|
-
end
|
412
|
+
match 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' }
|
541
413
|
</ruby>
|
542
414
|
|
543
|
-
Rails
|
415
|
+
Rails would match +photos/12+ to the +show+ action of +PhotosController+, and set +params[:format]+ to +"jpg"+.
|
544
416
|
|
545
|
-
|
546
|
-
<%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %>
|
547
|
-
</ruby>
|
417
|
+
h4. Naming Routes
|
548
418
|
|
549
|
-
|
419
|
+
You can specify a name for any route using the +:as+ option.
|
550
420
|
|
551
421
|
<ruby>
|
552
|
-
|
422
|
+
match 'logout' => 'sessions#destroy', :as => :logout
|
553
423
|
</ruby>
|
554
424
|
|
555
|
-
This
|
425
|
+
This will create +logout_path+ and +logout_url+ as named helpers in your application. Calling +logout_path+ will return +/logout+
|
556
426
|
|
557
|
-
h4.
|
427
|
+
h4. Segment Constraints
|
558
428
|
|
559
|
-
|
429
|
+
You can use the +:constraints+ option to enforce a format for a dynamic segment:
|
560
430
|
|
561
431
|
<ruby>
|
562
|
-
|
563
|
-
resources :tags, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_tags'
|
564
|
-
resources :ratings, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_ratings'
|
432
|
+
match 'photo/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
|
565
433
|
</ruby>
|
566
434
|
|
567
|
-
|
435
|
+
This route would match URLs such as +/photo/A12345+. You can more succinctly express the same route this way:
|
568
436
|
|
569
437
|
<ruby>
|
570
|
-
|
571
|
-
resources :photos, :has_many => { :tags, :ratings }
|
572
|
-
end
|
438
|
+
match 'photo/:id' => 'photos#show', :id => /[A-Z]\d{5}/
|
573
439
|
</ruby>
|
574
440
|
|
575
|
-
|
576
|
-
|
577
|
-
h4. Adding More RESTful Actions
|
441
|
+
h4. Request-Based Constraints
|
578
442
|
|
579
|
-
You
|
580
|
-
|
581
|
-
h5. Adding Member Routes
|
443
|
+
You can also constrain a route based on any method on the <a href="action_controller_overview.html#the-request-object">Request</a> object that returns a +String+.
|
582
444
|
|
583
|
-
|
445
|
+
You specify a request-based constraint the same way that you specify a segment constraint:
|
584
446
|
|
585
447
|
<ruby>
|
586
|
-
|
587
|
-
member do
|
588
|
-
get :preview
|
589
|
-
end
|
590
|
-
end
|
448
|
+
match "photo", :constraints => {:subdomain => "admin"}
|
591
449
|
</ruby>
|
592
450
|
|
593
|
-
|
594
|
-
|
595
|
-
Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, +delete+, or +any+ here. If you don't have multiple +member+ route, you can also passing +:on+ to the routing.
|
451
|
+
You can also specify constrains in a block form:
|
596
452
|
|
597
453
|
<ruby>
|
598
|
-
|
599
|
-
|
454
|
+
namespace "admin" do
|
455
|
+
constraints :subdomain => "admin" do
|
456
|
+
resources :photos
|
457
|
+
end
|
600
458
|
end
|
601
459
|
</ruby>
|
602
460
|
|
603
|
-
|
461
|
+
h4. Advanced Constraints
|
604
462
|
|
605
|
-
|
463
|
+
If you have a more advanced constraint, you can provide an object that responds to +matches?+ that Rails should use. Let's say you wanted to route all users on a blacklist to the +BlacklistController+. You could do:
|
606
464
|
|
607
465
|
<ruby>
|
608
|
-
|
609
|
-
|
610
|
-
|
466
|
+
class BlacklistConstraint
|
467
|
+
def initialize
|
468
|
+
@ips = Blacklist.retrieve_ips
|
611
469
|
end
|
612
|
-
end
|
613
|
-
</ruby>
|
614
470
|
|
615
|
-
|
616
|
-
|
617
|
-
|
471
|
+
def matches?(request)
|
472
|
+
@ips.include?(request.remote_ip)
|
473
|
+
end
|
474
|
+
end
|
618
475
|
|
619
|
-
|
620
|
-
|
621
|
-
|
476
|
+
TwitterClone::Application.routes.draw do
|
477
|
+
match "*path" => "blacklist#index",
|
478
|
+
:constraints => BlacklistConstraint.new
|
622
479
|
end
|
623
480
|
</ruby>
|
624
481
|
|
625
|
-
|
482
|
+
h4. Route Globbing
|
626
483
|
|
627
|
-
|
484
|
+
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example
|
628
485
|
|
629
486
|
<ruby>
|
630
|
-
|
631
|
-
match 'photos/new/upload' => 'photos#upload', :as => 'upload_new_photos'
|
487
|
+
match 'photo/*other' => 'photos#unknown'
|
632
488
|
</ruby>
|
633
489
|
|
634
|
-
|
490
|
+
This route would match +photo/12+ or +/photo/long/path/to/12+, setting +params[:other]+ to +"12"+ or +"long/path/to/12"+.
|
635
491
|
|
636
|
-
|
492
|
+
h4. Redirection
|
637
493
|
|
638
|
-
|
494
|
+
You can redirect any path to another path using the +redirect+ helper in your router:
|
639
495
|
|
640
|
-
|
496
|
+
<ruby>
|
497
|
+
match "/stories" => redirect("/posts")
|
498
|
+
</ruby>
|
641
499
|
|
642
|
-
|
500
|
+
You can also reuse dynamic segments from the match in the path to redirect to:
|
643
501
|
|
644
|
-
|
502
|
+
<ruby>
|
503
|
+
match "/stories/:name" => redirect("/posts/%{name}")
|
504
|
+
</ruby>
|
645
505
|
|
646
|
-
|
506
|
+
You can also provide a block to redirect, which receives the params and (optionally) the request object:
|
647
507
|
|
648
508
|
<ruby>
|
649
|
-
match
|
509
|
+
match "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" }
|
510
|
+
match "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" }
|
650
511
|
</ruby>
|
651
512
|
|
652
|
-
|
513
|
+
In all of these cases, if you don't provide the leading host (+http://www.example.com+), Rails will take those details from the current request.
|
653
514
|
|
654
|
-
h4.
|
515
|
+
h4. Routing to Rack Applications
|
655
516
|
|
656
|
-
|
517
|
+
Instead of a String, like +"posts#index"+, which corresponds to the +index+ action in the +PostsController+, you can specify any <a href="rails_on_rack.html">Rack application</a> as the endpoint for a matcher.
|
657
518
|
|
658
519
|
<ruby>
|
659
|
-
match
|
520
|
+
match "/application.js" => Sprockets
|
660
521
|
</ruby>
|
661
522
|
|
662
|
-
|
523
|
+
As long as +Sprockets+ responds to +call+ and returns a <tt>[status, headers, body]</tt>, the router won't know the difference between the Rack application and an action.
|
663
524
|
|
664
|
-
|
525
|
+
NOTE: For the curious, +"posts#index"+ actually expands out to +PostsController.action(:index)+, which returns a valid Rack application.
|
665
526
|
|
666
|
-
|
527
|
+
h4. Using +root+
|
528
|
+
|
529
|
+
You can specify what Rails should route +"/"+ to with the +root+ method:
|
667
530
|
|
668
531
|
<ruby>
|
669
|
-
|
532
|
+
root :to => 'pages#main'
|
670
533
|
</ruby>
|
671
534
|
|
672
|
-
|
535
|
+
You should put the +root+ route at the end of the file.
|
536
|
+
|
537
|
+
h3. Customizing Resourceful Routes
|
538
|
+
|
539
|
+
While the default routes and helpers generated by +resources :posts+ will usually serve you well, you may want to customize them in some way. Rails allows you to customize virtually any generic part of the resourceful helpers.
|
673
540
|
|
674
|
-
h4.
|
541
|
+
h4. Specifying a Controller to Use
|
675
542
|
|
676
|
-
|
543
|
+
The +:controller+ option lets you explicitly specify a controller to use for the resource. For example:
|
677
544
|
|
678
545
|
<ruby>
|
679
|
-
|
546
|
+
resources :photos, :controller => "images"
|
680
547
|
</ruby>
|
681
548
|
|
682
|
-
|
549
|
+
will recognize incoming URLs beginning with +/photo+ but route to the +Images+ controller:
|
683
550
|
|
684
|
-
|
551
|
+
|_. Verb |_.URL |_.action |
|
552
|
+
|GET |/photos |index |
|
553
|
+
|GET |/photos/new |new |
|
554
|
+
|POST |/photos |create |
|
555
|
+
|GET |/photos/1 |show |
|
556
|
+
|GET |/photos/1/edit |edit |
|
557
|
+
|PUT |/photos/1 |update |
|
558
|
+
|DELETE |/photos/1 |destroy |
|
559
|
+
|
560
|
+
NOTE: Use +photos_path+, +new_photos_path+, etc. to generate URLs for this resource.
|
561
|
+
|
562
|
+
h4. Specifying Constraints
|
685
563
|
|
686
|
-
You
|
564
|
+
You can use the +:constraints+ option to specify a required format on the implicit +id+. For example:
|
687
565
|
|
688
566
|
<ruby>
|
689
|
-
|
567
|
+
resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/}
|
690
568
|
</ruby>
|
691
569
|
|
692
|
-
|
570
|
+
This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, the router would no longer match +/photos/1+ to this route. Instead, +/photos/RR27+ would match.
|
693
571
|
|
694
|
-
You can
|
572
|
+
You can specify a single constraint to a apply to a number of routes by using the block form:
|
695
573
|
|
696
574
|
<ruby>
|
697
|
-
|
575
|
+
constraints(:id => /[A-Z][A-Z][0-9]+/) do
|
576
|
+
resources :photos
|
577
|
+
resources :accounts
|
578
|
+
end
|
698
579
|
</ruby>
|
699
580
|
|
700
|
-
|
581
|
+
NOTE: Of course, you can use the more advanced constraints available in non-resourceful routes in this context
|
701
582
|
|
702
|
-
h4. Named
|
583
|
+
h4. Overriding the Named Helpers
|
703
584
|
|
704
|
-
|
585
|
+
The +:as+ option lets you override the normal naming for the named route helpers. For example:
|
705
586
|
|
706
587
|
<ruby>
|
707
|
-
|
588
|
+
resources :photos, :as => "images"
|
708
589
|
</ruby>
|
709
590
|
|
710
|
-
|
591
|
+
will recognize incoming URLs beginning with +/photos+ and route the requests to +PhotosController+:
|
592
|
+
|
593
|
+
|_.HTTP verb|_.URL |_.action |_.named helper |
|
594
|
+
|GET |/photos |index | images_path_ |
|
595
|
+
|GET |/photos/new |new | new_image_path |
|
596
|
+
|POST |/photos |create | images_path |
|
597
|
+
|GET |/photos/1 |show | image_path |
|
598
|
+
|GET |/photos/1/edit |edit | edit_image_path |
|
599
|
+
|PUT |/photos/1 |update | image_path |
|
600
|
+
|DELETE |/photos/1 |destroy | image_path |
|
711
601
|
|
712
|
-
h4.
|
602
|
+
h4. Overriding the +new+ and +edit+ Segments
|
713
603
|
|
714
|
-
|
604
|
+
The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in URLs:
|
715
605
|
|
716
606
|
<ruby>
|
717
|
-
|
607
|
+
resources :photos, :path_names => { :new => 'make', :edit => 'change' }
|
718
608
|
</ruby>
|
719
609
|
|
720
|
-
This
|
610
|
+
This would cause the routing to recognize URLs such as
|
721
611
|
|
722
|
-
<
|
723
|
-
|
724
|
-
|
612
|
+
<plain>
|
613
|
+
/photos/make
|
614
|
+
/photos/1/change
|
615
|
+
</plain>
|
725
616
|
|
726
|
-
|
617
|
+
NOTE: The actual action names aren't changed by this option. The two URLs shown would still route to the new and edit actions.
|
727
618
|
|
728
|
-
|
619
|
+
TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can use a scope:
|
729
620
|
|
730
621
|
<ruby>
|
731
|
-
|
622
|
+
scope :path_names => { :new => "make" } do
|
623
|
+
# rest of your routes
|
624
|
+
end
|
732
625
|
</ruby>
|
733
626
|
|
734
|
-
|
735
|
-
|
736
|
-
h4. Route Globbing
|
627
|
+
h4. Overriding the Named Helper Prefix
|
737
628
|
|
738
|
-
|
629
|
+
You can use the :name_prefix option to add a prefix to the named route helpers that Rails generates for a route. You can use this option to prevent collisions between routes using a path scope.
|
739
630
|
|
740
631
|
<ruby>
|
741
|
-
|
742
|
-
|
632
|
+
scope "admin" do
|
633
|
+
resources :photos, :name_prefix => "admin"
|
634
|
+
end
|
743
635
|
|
744
|
-
|
636
|
+
resources :photos
|
637
|
+
</ruby>
|
745
638
|
|
746
|
-
|
639
|
+
This will provide route helpers such as +photographer_photos_path+.
|
747
640
|
|
748
|
-
You
|
641
|
+
You could specify a name prefix to use for a group of routes in the scope:
|
749
642
|
|
750
643
|
<ruby>
|
751
|
-
|
752
|
-
|
753
|
-
photo.delete ':id/delete', :action => 'delete'
|
754
|
-
photo.edit ':id/edit', :action => 'edit'
|
644
|
+
scope "admin", :name_prefix => "admin" do
|
645
|
+
resources :photos, :accounts
|
755
646
|
end
|
756
|
-
</ruby>
|
757
647
|
|
758
|
-
|
648
|
+
resources :photos, :accounts
|
649
|
+
</ruby>
|
759
650
|
|
760
|
-
|
651
|
+
NOTE: The +namespace+ scope will automatically add a +:name_prefix+ as well as +:module+ and +:path+ prefixes.
|
761
652
|
|
762
|
-
|
653
|
+
h4. Restricting the Routes Created
|
763
654
|
|
764
|
-
|
655
|
+
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 tells Rails to create only the specified routes:
|
765
656
|
|
766
657
|
<ruby>
|
767
|
-
|
658
|
+
resources :photos, :only => [:index, :show]
|
768
659
|
</ruby>
|
769
660
|
|
770
|
-
|
661
|
+
Now, a +GET+ request to +/photos+ would succeed, but a +POST+ request to +/photos+ (which would ordinarily be routed to the +create+ action) will fail.
|
662
|
+
|
663
|
+
The +:except+ option specifies a route or list of routes that Rails should _not_ create:
|
771
664
|
|
772
665
|
<ruby>
|
773
|
-
|
774
|
-
format.html # return the default template for HTML
|
775
|
-
format.xml { render :xml => @photo.to_xml }
|
776
|
-
end
|
666
|
+
resources :photos, :except => :destroy
|
777
667
|
</ruby>
|
778
668
|
|
779
|
-
|
780
|
-
|
781
|
-
If there is no +:format+ parameter in the route, Rails will automatically look at the HTTP Accept header to determine the desired format.
|
782
|
-
|
783
|
-
h4. Recognized MIME types
|
669
|
+
In this case, Rails will create all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/:id+).
|
784
670
|
|
785
|
-
|
786
|
-
|
787
|
-
<ruby>
|
788
|
-
Mime::Type.register "image/jpg", :jpg
|
789
|
-
</ruby>
|
671
|
+
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.
|
790
672
|
|
791
|
-
|
673
|
+
h4. Translated Paths
|
792
674
|
|
793
|
-
|
675
|
+
Using +scope+, we can alter path names generated by resources:
|
794
676
|
|
795
677
|
<ruby>
|
796
|
-
|
678
|
+
scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do
|
679
|
+
resources :categories, :path => "kategorien"
|
680
|
+
end
|
797
681
|
</ruby>
|
798
682
|
|
799
|
-
|
683
|
+
Rails now creates routes to the +CategoriesControlleR+.
|
800
684
|
|
801
|
-
|
685
|
+
|_.HTTP verb|_.URL |_.action |
|
686
|
+
|GET |/kategorien |index |
|
687
|
+
|GET |/kategorien/neu |new |
|
688
|
+
|POST |/kategorien |create |
|
689
|
+
|GET |/kategorien/1 |show |
|
690
|
+
|GET |/kategorien/:id/bearbeiten |edit |
|
691
|
+
|PUT |/kategorien/1 |update |
|
692
|
+
|DELETE |/kategorien/1 |destroy |
|
802
693
|
|
803
|
-
|
694
|
+
h4. Overriding the Singular Form
|
804
695
|
|
805
|
-
|
806
|
-
|
807
|
-
h4. Using +root+
|
808
|
-
|
809
|
-
The preferred way to set up the empty route is with the +root+ command:
|
696
|
+
If you want to customize the singular name of the route in the named helpers, you can use the +:singular+ option.
|
810
697
|
|
811
698
|
<ruby>
|
812
|
-
|
699
|
+
resources :teeth, :singular => "tooth"
|
813
700
|
</ruby>
|
814
701
|
|
815
|
-
|
702
|
+
TIP: If you want to define the singular form of a word for your entire application, you should add additional rules to the +Inflector+ instead.
|
816
703
|
|
817
|
-
|
704
|
+
h4(#nested-name-prefix). Using +:name_prefix+ in Nested Resources
|
818
705
|
|
819
|
-
|
820
|
-
|
821
|
-
You can also specify an empty route by explicitly connecting the empty string:
|
706
|
+
The +:name_prefix+ option overrides the automatically-generated prefix for the parent resource in nested route helpers. For example,
|
822
707
|
|
823
708
|
<ruby>
|
824
|
-
|
709
|
+
resources :magazines do
|
710
|
+
resources :ads, :name_prefix => 'periodical'
|
711
|
+
end
|
825
712
|
</ruby>
|
826
713
|
|
827
|
-
|
714
|
+
This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+.
|
828
715
|
|
829
716
|
h3. Inspecting and Testing Routes
|
830
717
|
|
831
|
-
|
718
|
+
Rails offers facilities for inspecting and testing your routes.
|
832
719
|
|
833
720
|
h4. Seeing Existing Routes with +rake+
|
834
721
|
|
835
|
-
If you want a complete list of all of the available routes in your application, run
|
722
|
+
If you want a complete list of all of the available routes in your application, run +rake routes+ command. This will print all of your routes, in the same order that they appear in +routes.rb+. For each route, you'll see:
|
836
723
|
|
837
724
|
* The route name (if any)
|
838
725
|
* The HTTP verb used (if the route doesn't respond to all verbs)
|
839
|
-
* The URL pattern
|
840
|
-
* The routing parameters
|
726
|
+
* The URL pattern to match
|
727
|
+
* The routing parameters for the route
|
841
728
|
|
842
729
|
For example, here's a small section of the +rake routes+ output for a RESTful route:
|
843
730
|
|
@@ -881,7 +768,7 @@ You can supply a +:method+ argument to specify the HTTP verb:
|
|
881
768
|
assert_recognizes({ :controller => "photos", :action => "create" }, { :path => "photos", :method => :post })
|
882
769
|
</ruby>
|
883
770
|
|
884
|
-
You can also use the
|
771
|
+
You can also use the resourceful helpers to test recognition of a RESTful route:
|
885
772
|
|
886
773
|
<ruby>
|
887
774
|
assert_recognizes new_photo_url, { :path => "photos", :method => :post }
|
@@ -899,6 +786,8 @@ h3. Changelog
|
|
899
786
|
|
900
787
|
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3
|
901
788
|
|
789
|
+
* April 10, 2010: Updated guide to remove outdated and superfluous information, and to provide information about new features, by "Yehuda Katz":http://www.yehudakatz.com
|
790
|
+
* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by "Rizwan Reza":http://www.rizwanreza.com/
|
902
791
|
* Febuary 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist
|
903
792
|
* October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy
|
904
793
|
* September 23, 2008: Added section on namespaced controllers and routing, by "Mike Gunderloy":credits.html#mgunderloy
|