railties 3.0.20 → 3.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. data/CHANGELOG +36 -49
  2. data/README.rdoc +2 -1
  3. data/guides/assets/stylesheets/fixes.css +16 -0
  4. data/guides/rails_guides.rb +2 -2
  5. data/guides/rails_guides/generator.rb +8 -3
  6. data/guides/rails_guides/textile_extensions.rb +4 -2
  7. data/guides/source/2_2_release_notes.textile +3 -3
  8. data/guides/source/2_3_release_notes.textile +2 -2
  9. data/guides/source/3_0_release_notes.textile +14 -14
  10. data/guides/source/action_controller_overview.textile +54 -79
  11. data/guides/source/action_mailer_basics.textile +39 -9
  12. data/guides/source/action_view_overview.textile +257 -211
  13. data/guides/source/active_record_basics.textile +1 -1
  14. data/guides/source/active_record_querying.textile +217 -27
  15. data/guides/source/active_record_validations_callbacks.textile +94 -25
  16. data/guides/source/active_support_core_extensions.textile +109 -77
  17. data/guides/source/ajax_on_rails.textile +15 -150
  18. data/guides/source/api_documentation_guidelines.textile +12 -12
  19. data/guides/source/association_basics.textile +74 -60
  20. data/guides/source/caching_with_rails.textile +59 -60
  21. data/guides/source/command_line.textile +46 -47
  22. data/guides/source/configuring.textile +55 -37
  23. data/guides/source/contribute.textile +7 -7
  24. data/guides/source/contributing_to_ruby_on_rails.textile +14 -23
  25. data/guides/source/credits.html.erb +3 -3
  26. data/guides/source/debugging_rails_applications.textile +59 -46
  27. data/guides/source/form_helpers.textile +76 -31
  28. data/guides/source/generators.textile +39 -40
  29. data/guides/source/getting_started.textile +73 -94
  30. data/guides/source/i18n.textile +64 -58
  31. data/guides/source/index.html.erb +3 -3
  32. data/guides/source/initialization.textile +634 -3284
  33. data/guides/source/layout.html.erb +6 -7
  34. data/guides/source/layouts_and_rendering.textile +59 -60
  35. data/guides/source/migrations.textile +63 -59
  36. data/guides/source/nested_model_forms.textile +2 -2
  37. data/guides/source/performance_testing.textile +16 -16
  38. data/guides/source/plugins.textile +236 -1280
  39. data/guides/source/rails_application_templates.textile +37 -29
  40. data/guides/source/rails_on_rack.textile +4 -9
  41. data/guides/source/routing.textile +96 -75
  42. data/guides/source/ruby_on_rails_guides_guidelines.textile +19 -12
  43. data/guides/source/security.textile +57 -30
  44. data/guides/source/testing.textile +26 -24
  45. data/guides/w3c_validator.rb +2 -2
  46. data/lib/rails.rb +1 -7
  47. data/lib/rails/application.rb +46 -76
  48. data/lib/rails/application/bootstrap.rb +6 -11
  49. data/lib/rails/application/configuration.rb +43 -40
  50. data/lib/rails/application/finisher.rb +16 -4
  51. data/lib/rails/application/railties.rb +6 -24
  52. data/lib/rails/application/routes_reloader.rb +45 -0
  53. data/lib/rails/backtrace_cleaner.rb +1 -1
  54. data/lib/rails/cli.rb +7 -5
  55. data/lib/rails/commands.rb +27 -2
  56. data/lib/rails/commands/application.rb +14 -1
  57. data/lib/rails/commands/benchmarker.rb +3 -1
  58. data/lib/rails/commands/dbconsole.rb +2 -2
  59. data/lib/rails/commands/destroy.rb +3 -1
  60. data/lib/rails/commands/generate.rb +3 -1
  61. data/lib/rails/commands/plugin.rb +2 -7
  62. data/lib/rails/commands/plugin_new.rb +10 -0
  63. data/lib/rails/commands/profiler.rb +3 -1
  64. data/lib/rails/commands/server.rb +4 -0
  65. data/lib/rails/configuration.rb +8 -81
  66. data/lib/rails/console/app.rb +2 -2
  67. data/lib/rails/engine.rb +460 -78
  68. data/lib/rails/engine/configuration.rb +46 -49
  69. data/lib/rails/engine/railties.rb +33 -0
  70. data/lib/rails/generators.rb +11 -5
  71. data/lib/rails/generators/actions.rb +2 -27
  72. data/lib/rails/generators/app_base.rb +216 -0
  73. data/lib/rails/generators/base.rb +3 -2
  74. data/lib/rails/generators/erb/scaffold/templates/index.html.erb +1 -1
  75. data/lib/rails/generators/generated_attribute.rb +2 -1
  76. data/lib/rails/generators/migration.rb +6 -2
  77. data/lib/rails/generators/named_base.rb +79 -3
  78. data/lib/rails/generators/rails/app/app_generator.rb +44 -209
  79. data/lib/rails/generators/rails/app/templates/Gemfile +15 -31
  80. data/lib/rails/generators/rails/app/templates/README +2 -2
  81. data/lib/rails/generators/rails/app/templates/Rakefile +1 -1
  82. data/lib/rails/generators/rails/app/templates/{public → app/assets}/images/rails.png +0 -0
  83. data/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +8 -0
  84. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css +5 -0
  85. data/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory +0 -0
  86. data/lib/rails/generators/rails/app/templates/app/models/.empty_directory +0 -0
  87. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +4 -4
  88. data/lib/rails/generators/rails/app/templates/config/application.rb +19 -3
  89. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml +4 -4
  90. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml +11 -6
  91. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml +3 -3
  92. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +1 -1
  93. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +1 -2
  94. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +14 -11
  95. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -1
  96. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +1 -1
  97. data/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt +12 -0
  98. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +1 -1
  99. data/lib/rails/generators/rails/app/templates/config/routes.rb +1 -1
  100. data/lib/rails/generators/rails/app/templates/db/{seeds.rb → seeds.rb.tt} +2 -2
  101. data/lib/rails/generators/rails/app/templates/public/index.html +10 -8
  102. data/lib/rails/generators/rails/app/templates/public/stylesheets/.empty_directory +0 -0
  103. data/lib/rails/generators/rails/app/templates/test/fixtures/.empty_directory +0 -0
  104. data/lib/rails/generators/rails/app/templates/test/functional/.empty_directory +0 -0
  105. data/lib/rails/generators/rails/app/templates/test/integration/.empty_directory +0 -0
  106. data/lib/rails/generators/rails/app/templates/test/{test_helper.rb.tt → test_helper.rb} +0 -0
  107. data/lib/rails/generators/rails/app/templates/test/unit/.empty_directory +0 -0
  108. data/lib/rails/generators/rails/assets/USAGE +20 -0
  109. data/lib/rails/generators/rails/assets/assets_generator.rb +39 -0
  110. data/lib/rails/generators/rails/assets/templates/javascript.js +2 -0
  111. data/lib/rails/generators/rails/assets/templates/javascript.js.coffee +3 -0
  112. data/lib/rails/generators/rails/assets/templates/stylesheet.css +4 -0
  113. data/lib/rails/generators/rails/assets/templates/stylesheet.css.scss +5 -0
  114. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  115. data/lib/rails/generators/rails/controller/templates/controller.rb +2 -0
  116. data/lib/rails/generators/rails/generator/generator_generator.rb +2 -2
  117. data/lib/rails/generators/rails/generator/templates/templates/.empty_directory +0 -0
  118. data/lib/rails/generators/rails/helper/templates/helper.rb +2 -0
  119. data/lib/rails/generators/rails/plugin/plugin_generator.rb +7 -0
  120. data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +4 -4
  121. data/lib/rails/generators/rails/plugin_new/USAGE +10 -0
  122. data/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +303 -0
  123. data/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +9 -0
  124. data/lib/rails/generators/rails/plugin_new/templates/Gemfile +11 -0
  125. data/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE +20 -0
  126. data/lib/rails/generators/rails/plugin_new/templates/README.rdoc +3 -0
  127. data/lib/rails/generators/rails/plugin_new/templates/Rakefile +21 -0
  128. data/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt +4 -0
  129. data/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt +4 -0
  130. data/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory +0 -0
  131. data/lib/rails/generators/rails/plugin_new/templates/config/routes.rb +6 -0
  132. data/lib/rails/generators/rails/plugin_new/templates/gitignore +6 -0
  133. data/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb +6 -0
  134. data/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb +7 -0
  135. data/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake +4 -0
  136. data/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +16 -0
  137. data/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb +10 -0
  138. data/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb +4 -0
  139. data/lib/rails/generators/rails/plugin_new/templates/script/rails.tt +5 -0
  140. data/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb +7 -0
  141. data/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb +12 -0
  142. data/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +10 -0
  143. data/lib/rails/generators/rails/resource/resource_generator.rb +2 -2
  144. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +20 -1
  145. data/lib/rails/generators/rails/{stylesheets → scaffold}/templates/scaffold.css +0 -0
  146. data/lib/rails/generators/rails/scaffold/templates/scaffold.css.scss +58 -0
  147. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +21 -19
  148. data/lib/rails/generators/resource_helpers.rb +3 -3
  149. data/lib/rails/generators/test_case.rb +2 -20
  150. data/lib/rails/generators/test_unit/controller/templates/functional_test.rb +5 -4
  151. data/lib/rails/generators/test_unit/helper/templates/helper_test.rb +2 -0
  152. data/lib/rails/generators/test_unit/integration/templates/integration_test.rb +3 -4
  153. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb +5 -4
  154. data/lib/rails/generators/test_unit/model/templates/fixtures.yml +1 -1
  155. data/lib/rails/generators/test_unit/model/templates/unit_test.rb +5 -4
  156. data/lib/rails/generators/test_unit/observer/templates/unit_test.rb +5 -4
  157. data/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt +3 -4
  158. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +7 -5
  159. data/lib/rails/info.rb +0 -1
  160. data/lib/rails/paths.rb +119 -65
  161. data/lib/rails/plugin.rb +18 -19
  162. data/lib/rails/rack/log_tailer.rb +1 -1
  163. data/lib/rails/railtie.rb +50 -47
  164. data/lib/rails/railtie/configurable.rb +20 -10
  165. data/lib/rails/railtie/configuration.rb +20 -19
  166. data/lib/rails/source_annotation_extractor.rb +5 -5
  167. data/lib/rails/tasks.rb +1 -0
  168. data/lib/rails/tasks/assets.rake +10 -0
  169. data/lib/rails/tasks/documentation.rake +2 -8
  170. data/lib/rails/tasks/engine.rake +69 -0
  171. data/lib/rails/tasks/framework.rake +4 -21
  172. data/lib/rails/tasks/misc.rake +1 -1
  173. data/lib/rails/tasks/routes.rake +2 -1
  174. data/lib/rails/test_help.rb +17 -1
  175. data/lib/rails/test_unit/railtie.rb +1 -1
  176. data/lib/rails/test_unit/testing.rake +8 -3
  177. data/lib/rails/version.rb +3 -3
  178. metadata +128 -100
  179. checksums.yaml +0 -7
  180. data/lib/rails/application/configurable.rb +0 -19
  181. data/lib/rails/console/sandbox.rb +0 -6
  182. data/lib/rails/deprecation.rb +0 -41
  183. data/lib/rails/engine/configurable.rb +0 -25
  184. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml +0 -62
  185. data/lib/rails/generators/rails/app/templates/public/javascripts/application.js +0 -2
  186. data/lib/rails/generators/rails/app/templates/public/javascripts/controls.js +0 -965
  187. data/lib/rails/generators/rails/app/templates/public/javascripts/dragdrop.js +0 -974
  188. data/lib/rails/generators/rails/app/templates/public/javascripts/effects.js +0 -1123
  189. data/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js +0 -6001
  190. data/lib/rails/generators/rails/app/templates/public/javascripts/rails.js +0 -202
  191. data/lib/rails/generators/rails/stylesheets/USAGE +0 -5
  192. data/lib/rails/generators/rails/stylesheets/stylesheets_generator.rb +0 -9
  193. data/lib/rails/info_routes.rb +0 -3
@@ -9,6 +9,7 @@ In this guide you will:
9
9
  * Generate select boxes from multiple types of data
10
10
  * Understand the date and time helpers Rails provides
11
11
  * Learn what makes a file upload form different
12
+ * Learn some cases of building forms to external resources
12
13
  * Find out where to look for complex forms
13
14
 
14
15
  endprologue.
@@ -31,17 +32,18 @@ When called without arguments like this, it creates a form element that has the
31
32
  Sample output from +form_tag+:
32
33
 
33
34
  <html>
34
- <form action="/home/index" method="post">
35
+ <form accept-charset="UTF-8" action="/home/index" method="post">
35
36
  <div style="margin:0;padding:0">
37
+ <input name="utf8" type="hidden" value="&#x2713;" />
36
38
  <input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
37
39
  </div>
38
40
  Form contents
39
41
  </form>
40
42
  </html>
41
43
 
42
- If you carefully observe this output, you can see that the helper generated something you didn't specify: a +div+ element with a hidden input inside. This is a security feature of Rails called *cross-site request forgery protection* and form helpers generate it for every form whose action is not "get" (provided that this security feature is enabled). You can read more about this in the "Ruby On Rails Security Guide":./security.html#_cross_site_reference_forgery_csrf.
44
+ If you carefully observe this output, you can see that the helper generated something you didn't specify: a +div+ element with two hidden input elements inside. The first input element with name +utf8+ enforces browsers to properly respect your form's character encoding and is generated for all forms whether action is "get" or "post". Second input element with name +authenticity_token+ is a security feature of Rails called *cross-site request forgery protection* and form helpers generate it for every form whose action is not "get" (provided that this security feature is enabled). You can read more about this in the "Ruby On Rails Security Guide":./security.html#_cross_site_reference_forgery_csrf.
43
45
 
44
- NOTE: Throughout this guide, this +div+ with the hidden input will be stripped away to have clearer code samples.
46
+ NOTE: Throughout this guide, this +div+ with the hidden input elements will be stripped away to have clearer code samples.
45
47
 
46
48
  h4. A Generic Search Form
47
49
 
@@ -66,12 +68,12 @@ A basic search form
66
68
  <% end %>
67
69
  </erb>
68
70
 
69
- TIP: +search_path+ can be a named route specified in "routes.rb": <br /><tt>map.search "search", :controller => "search"</tt>
71
+ TIP: +search_path+ can be a named route specified in "routes.rb" as: <br /><code>match "search" => "search"</code> This declares that path "/search" will be handled by action "search" belonging to controller "search".
70
72
 
71
73
  The above view code will result in the following markup:
72
74
 
73
75
  <html>
74
- <form action="/search" method="get">
76
+ <form accept-charset="UTF-8" action="/search" method="get">
75
77
  <label for="q">Search for:</label>
76
78
  <input id="q" name="q" type="text" />
77
79
  <input name="commit" type="submit" value="Search" />
@@ -90,14 +92,14 @@ As with the +link_to+ helper, the path argument doesn't have to be given a strin
90
92
 
91
93
  <ruby>
92
94
  form_tag(:controller => "people", :action => "search", :method => "get", :class => "nifty_form")
93
- # => <form action="/people/search?method=get&class=nifty_form" method="post">
95
+ # => <form accept-charset="UTF-8" action="/people/search?method=get&class=nifty_form" method="post">
94
96
  </ruby>
95
97
 
96
98
  Here you wanted to pass two hashes, but the Ruby interpreter sees only one hash, so Rails will construct a URL with extraneous parameters. The correct way of passing multiple hashes as arguments is to delimit the first hash (or both hashes) with curly brackets:
97
99
 
98
100
  <ruby>
99
101
  form_tag({:controller => "people", :action => "search"}, :method => "get", :class => "nifty_form")
100
- # => <form action="/people/search" method="get" class="nifty_form">
102
+ # => <form accept-charset="UTF-8" action="/people/search" method="get" class="nifty_form">
101
103
  </ruby>
102
104
 
103
105
  This is a common pitfall when using form helpers, since many of them accept multiple hashes. So in future, if a helper produces unexpected output, make sure that you have delimited the hash parameters properly.
@@ -106,7 +108,7 @@ WARNING: Do not delimit the second hash without doing so with the first hash, ot
106
108
 
107
109
  h4. Helpers for Generating Form Elements
108
110
 
109
- Rails provides a series of helpers for generating form elements such as checkboxes, text fields, radio buttons, and so on. These basic helpers, with names ending in <notextile>_tag</notextile> such as +text_field_tag+, +check_box_tag+, generate just a single +&lt;input&gt;+ element. The first parameter to these is always the name of the input. In the controller this name will be the key in the +params+ hash used to get the value entered by the user. For example, if the form contains
111
+ Rails provides a series of helpers for generating form elements such as checkboxes, text fields and radio buttons. These basic helpers, with names ending in <notextile>_tag</notextile> such as +text_field_tag+ and +check_box_tag+ generate just a single +&lt;input&gt;+ element. The first parameter to these is always the name of the input. In the controller this name will be the key in the +params+ hash used to get the value entered by the user. For example, if the form contains
110
112
 
111
113
  <erb>
112
114
  <%= text_field_tag(:query) %>
@@ -186,7 +188,7 @@ output:
186
188
 
187
189
  Hidden inputs are not shown to the user, but they hold data like any textual input. Values inside them can be changed with JavaScript.
188
190
 
189
- TIP: If you're using password input fields (for any purpose), you might want to prevent their values showing up in application logs by activating +filter_parameter_logging(:password)+ in your ApplicationController.
191
+ TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged.
190
192
 
191
193
 
192
194
  h3. Dealing with Model Objects
@@ -228,16 +230,16 @@ end
228
230
  The corresponding view +app/views/articles/new.html.erb+ using +form_for+ looks like this:
229
231
 
230
232
  <erb>
231
- <%= form_for :article, @article, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
233
+ <%= form_for @article, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
232
234
  <%= f.text_field :title %>
233
235
  <%= f.text_area :body, :size => "60x12" %>
234
- <%= submit_tag "Create" %>
236
+ <%= f.submit "Create" %>
235
237
  <% end %>
236
238
  </erb>
237
239
 
238
240
  There are a few things to note here:
239
241
 
240
- # +:article+ is the name of the model and +@article+ is the actual object being edited.
242
+ # +@article+ is the actual object being edited.
241
243
  # There is a single hash of options. Routing options are passed in the +:url+ hash, HTML options are passed in the +:html+ hash.
242
244
  # The +form_for+ method yields a *form builder* object (the +f+ variable).
243
245
  # Methods to create form controls are called *on* the form builder object +f+
@@ -245,7 +247,7 @@ There are a few things to note here:
245
247
  The resulting HTML is:
246
248
 
247
249
  <html>
248
- <form action="/articles/create" method="post" class="nifty_form">
250
+ <form accept-charset="UTF-8" action="/articles/create" method="post" class="nifty_form">
249
251
  <input id="article_title" name="article[title]" size="30" type="text" />
250
252
  <textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
251
253
  <input name="commit" type="submit" value="Create" />
@@ -256,10 +258,10 @@ The name passed to +form_for+ controls the key used in +params+ to access the fo
256
258
 
257
259
  The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder.
258
260
 
259
- You can create a similar binding without actually creating +&lt;form&gt;+ tags with the +fields_for+ helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
261
+ You can create a similar binding without actually creating +&lt;form&gt;+ tags with the +fields_for+ helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
260
262
 
261
263
  <erb>
262
- <%= form_for :person, @person, :url => { :action => "create" } do |person_form| %>
264
+ <%= form_for @person, :url => { :action => "create" } do |person_form| %>
263
265
  <%= person_form.text_field :name %>
264
266
  <%= fields_for @person.contact_detail do |contact_details_form| %>
265
267
  <%= contact_details_form.text_field :phone_number %>
@@ -270,7 +272,7 @@ You can create a similar binding without actually creating +&lt;form&gt;+ tags
270
272
  which produces the following output:
271
273
 
272
274
  <html>
273
- <form action="/people/create" class="new_person" id="new_person" method="post">
275
+ <form accept-charset="UTF-8" action="/people/create" class="new_person" id="new_person" method="post">
274
276
  <input id="person_name" name="person[name]" size="30" type="text" />
275
277
  <input id="contact_detail_phone_number" name="contact_detail[phone_number]" size="30" type="text" />
276
278
  </form>
@@ -293,13 +295,13 @@ When dealing with RESTful resources, calls to +form_for+ can get significantly e
293
295
  <ruby>
294
296
  ## Creating a new article
295
297
  # long-style:
296
- form_for(:article, @article, :url => articles_path)
298
+ form_for(@article, :url => articles_path)
297
299
  # same thing, short-style (record identification gets used):
298
300
  form_for(@article)
299
301
 
300
302
  ## Editing an existing article
301
303
  # long-style:
302
- form_for(:article, @article, :url => article_path(@article), :html => { :method => "put" })
304
+ form_for(@article, :url => article_path(@article), :html => { :method => "put" })
303
305
  # short-style:
304
306
  form_for(@article)
305
307
  </ruby>
@@ -340,9 +342,10 @@ form_tag(search_path, :method => "put")
340
342
  output:
341
343
 
342
344
  <html>
343
- <form action="/search" method="post">
345
+ <form accept-charset="UTF-8" action="/search" method="post">
344
346
  <div style="margin:0;padding:0">
345
347
  <input name="_method" type="hidden" value="put" />
348
+ <input name="utf8" type="hidden" value="&#x2713;" />
346
349
  <input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
347
350
  </div>
348
351
  ...
@@ -435,7 +438,7 @@ As with other helpers, if you were to use the +select+ helper on a form builder
435
438
  <%= f.select(:city_id, ...) %>
436
439
  </erb>
437
440
 
438
- WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <tt> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </tt> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#_mass_assignment.
441
+ WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <tt> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </tt> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#_mass_assignment.
439
442
 
440
443
  h4. Option Tags from a Collection of Arbitrary Objects
441
444
 
@@ -472,7 +475,7 @@ To leverage time zone support in Rails, you have to ask your users what time zon
472
475
 
473
476
  There is also +time_zone_options_for_select+ helper for a more manual (therefore more customizable) way of doing this. Read the API documentation to learn about the possible arguments for these two methods.
474
477
 
475
- Rails _used_ to have a +country_select+ helper for choosing countries, but this has been extracted to the "country_select plugin":http://github.com/rails/country_select/tree/master. When using this, be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from Rails).
478
+ Rails _used_ to have a +country_select+ helper for choosing countries, but this has been extracted to the "country_select plugin":https://github.com/chrislerum/country_select. When using this, be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from Rails).
476
479
 
477
480
  h3. Using Date and Time Form Helpers
478
481
 
@@ -510,7 +513,7 @@ The +:prefix+ option is the key used to retrieve the hash of date components fro
510
513
  h4(#select-model-object-helpers). Model Object Helpers
511
514
 
512
515
  +select_date+ does not work well with forms that update or create Active Record objects as Active Record expects each element of the +params+ hash to correspond to one attribute.
513
- The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
516
+ The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
514
517
 
515
518
  <erb>
516
519
  <%= date_select :person, :birth_date %>
@@ -555,7 +558,7 @@ will produce the same output if the current year is 2009 and the value chosen by
555
558
 
556
559
  h3. Uploading Files
557
560
 
558
- A common task is uploading some sort of file, whether it's a picture of a person or a CSV file containing data to process. The most important thing to remember with file uploads is that the form's encoding *MUST* be set to "multipart/form-data". If you forget to do this the file will not be uploaded. This can be done by passing +:multi_part => true+ as an HTML option. This means that in the case of +form_tag+ it must be passed in the second options hash and in the case of +form_for+ inside the +:html+ hash.
561
+ A common task is uploading some sort of file, whether it's a picture of a person or a CSV file containing data to process. The most important thing to remember with file uploads is that the rendered form's encoding *MUST* be set to "multipart/form-data". If you use +form_for+, this is done automatically. If you use +form_tag+, you must set it yourself, as per the following example.
559
562
 
560
563
  The following two forms both upload a file.
561
564
 
@@ -564,11 +567,13 @@ The following two forms both upload a file.
564
567
  <%= file_field_tag 'picture' %>
565
568
  <% end %>
566
569
 
567
- <%= form_for @person, :html => {:multipart => true} do |f| %>
570
+ <%= form_for @person do |f| %>
568
571
  <%= f.file_field :picture %>
569
572
  <% end %>
570
573
  </erb>
571
574
 
575
+ NOTE: Since Rails 3.1, forms rendered using +form_for+ have their encoding set to <tt>multipart/form-data</tt> automatically once a +file_field+ is used inside the block. Previous versions required you to set this explicitly.
576
+
572
577
  Rails provides the usual pair of helpers: the barebones +file_field_tag+ and the model oriented +file_field+. The only difference with other helpers is that you cannot set a default value for file inputs as this would have no meaning. As you would expect in the first case the uploaded file is in +params[:picture]+ and in the second case in +params[:person][:picture]+.
573
578
 
574
579
  h4. What Gets Uploaded
@@ -584,13 +589,13 @@ def upload
584
589
  end
585
590
  </ruby>
586
591
 
587
- Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several plugins designed to assist with these. Two of the better known ones are "Attachment-Fu":http://github.com/technoweenie/attachment_fu and "Paperclip":http://www.thoughtbot.com/projects/paperclip.
592
+ Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several plugins designed to assist with these. Two of the better known ones are "Attachment-Fu":https://github.com/technoweenie/attachment_fu and "Paperclip":http://www.thoughtbot.com/projects/paperclip.
588
593
 
589
594
  NOTE: If the user has not selected a file the corresponding parameter will be an empty string.
590
595
 
591
596
  h4. Dealing with Ajax
592
597
 
593
- Unlike other forms making an asynchronous file upload form is not as simple as replacing +form_for+ with +remote_form_for+. With an Ajax form the serialization is done by JavaScript running inside the browser and since JavaScript cannot read files from your hard drive the file cannot be uploaded. The most common workaround is to use an invisible iframe that serves as the target for the form submission.
598
+ Unlike other forms making an asynchronous file upload form is not as simple as providing +form_for+ with <tt>:remote => true</tt>. With an Ajax form the serialization is done by JavaScript running inside the browser and since JavaScript cannot read files from your hard drive the file cannot be uploaded. The most common workaround is to use an invisible iframe that serves as the target for the form submission.
594
599
 
595
600
  h3. Customizing Form Builders
596
601
 
@@ -637,7 +642,12 @@ action for a Person model, +params[:model]+ would usually be a hash of all the a
637
642
 
638
643
  Fundamentally HTML forms don't know about any sort of structured data, all they generate is name–value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.
639
644
 
640
- TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example <tt> ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789" # => {"name"=>"fred", "phone"=>"0123456789"} </tt>
645
+ TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example,
646
+
647
+ <ruby>
648
+ ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789"
649
+ # => {"name"=>"fred", "phone"=>"0123456789"}
650
+ </ruby>
641
651
 
642
652
  h4. Basic Structures
643
653
 
@@ -713,7 +723,7 @@ You might want to render a form with a set of edit fields for each of a person's
713
723
  Assuming the person had two addresses, with ids 23 and 45 this would create output similar to this:
714
724
 
715
725
  <html>
716
- <form action="/people/1" class="edit_person" id="edit_person_1" method="post">
726
+ <form accept-charset="UTF-8" action="/people/1" class="edit_person" id="edit_person_1" method="post">
717
727
  <input id="person_name" name="person[name]" size="30" type="text" />
718
728
  <input id="person_address_23_city" name="person[address][23][city]" size="30" type="text" />
719
729
  <input id="person_address_45_city" name="person[address][45][city]" size="30" type="text" />
@@ -754,6 +764,40 @@ As a shortcut you can append [] to the name and omit the +:index+ option. This i
754
764
 
755
765
  produces exactly the same output as the previous example.
756
766
 
767
+ h3. Forms to external resources
768
+
769
+ If you need to post some data to an external resource it is still great to build your from using rails form helpers. But sometimes you need to set an +authenticity_token+ for this resource. You can do it by passing an +:authenticity_token => 'your_external_token'+ parameter to the +form_tag+ options:
770
+
771
+ <erb>
772
+ <%= form_tag 'http://farfar.away/form', :authenticity_token => 'external_token') do %>
773
+ Form contents
774
+ <% end %>
775
+ </erb>
776
+
777
+ Sometimes when you submit data to an external resource, like payment gateway, fields you can use in your form are limited by an external API. So you may want not to generate an +authenticity_token+ hidden field at all. For doing this just pass +false+ to the +:authenticity_token+ option:
778
+
779
+ <erb>
780
+ <%= form_tag 'http://farfar.away/form', :authenticity_token => 'external_token') do %>
781
+ Form contents
782
+ <% end %>
783
+ </erb>
784
+
785
+ The same technique is available for the +form_for+ too:
786
+
787
+ <erb>
788
+ <%= form_for @invoice, :url => external_url, :authenticity_token => 'external_token' do |f|
789
+ Form contents
790
+ <% end %>
791
+ </erb>
792
+
793
+ Or if you don't want to render an +authenticity_token+ field:
794
+
795
+ <erb>
796
+ <%= form_for @invoice, :url => external_url, :authenticity_token => false do |f|
797
+ Form contents
798
+ <% end %>
799
+ </erb>
800
+
757
801
  h3. Building Complex Forms
758
802
 
759
803
  Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:
@@ -761,12 +805,13 @@ Many apps grow beyond simple forms editing a single object. For example when cre
761
805
  * As of Rails 2.3, Rails includes "Nested Attributes":./2_3_release_notes.html#nested-attributes and "Nested Object Forms":./2_3_release_notes.html#nested-object-forms
762
806
  * Ryan Bates' series of Railscasts on "complex forms":http://railscasts.com/episodes/75
763
807
  * Handle Multiple Models in One Form from "Advanced Rails Recipes":http://media.pragprog.com/titles/fr_arr/multiple_models_one_form.pdf
764
- * Eloy Duran's "complex-forms-examples":http://github.com/alloy/complex-form-examples/ application
765
- * Lance Ivy's "nested_assignment":http://github.com/cainlevy/nested_assignment/tree/master plugin and "sample application":http://github.com/cainlevy/complex-form-examples/tree/cainlevy
766
- * James Golick's "attribute_fu":http://github.com/jamesgolick/attribute_fu plugin
808
+ * Eloy Duran's "complex-forms-examples":https://github.com/alloy/complex-form-examples/ application
809
+ * Lance Ivy's "nested_assignment":https://github.com/cainlevy/nested_assignment/tree/master plugin and "sample application":https://github.com/cainlevy/complex-form-examples/tree/cainlevy
810
+ * James Golick's "attribute_fu":https://github.com/jamesgolick/attribute_fu plugin
767
811
 
768
812
  h3. Changelog
769
813
 
814
+ * February 5, 2011: Added 'Forms to external resources' section. Timothy N. Tsvetkov <timothy.tsvetkov@gmail.com>
770
815
  * April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
771
816
 
772
817
  h3. Authors
@@ -34,7 +34,7 @@ $ rails generate helper --help
34
34
 
35
35
  h3. Creating Your First Generator
36
36
 
37
- Since Rails 3.0, generators are built on top of "Thor":http://github.com/wycats/thor. Thor provides powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named +initializer.rb+ inside +config/initializers+.
37
+ Since Rails 3.0, generators are built on top of "Thor":https://github.com/wycats/thor. Thor provides powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named +initializer.rb+ inside +config/initializers+.
38
38
 
39
39
  The first step is to create a file at +lib/generators/initializer_generator.rb+ with the following content:
40
40
 
@@ -149,7 +149,7 @@ generators/initializer_generator.rb
149
149
 
150
150
  If none is found you get an error message.
151
151
 
152
- INFO: The examples above put files under the application's +lib+ because said directoty belongs to +$LOAD_PATH+.
152
+ INFO: The examples above put files under the application's +lib+ because said directory belongs to +$LOAD_PATH+.
153
153
 
154
154
  h3. Customizing Your Workflow
155
155
 
@@ -190,7 +190,7 @@ $ rails generate scaffold User name:string
190
190
  invoke test_unit
191
191
  create test/unit/helpers/users_helper_test.rb
192
192
  invoke stylesheets
193
- create public/stylesheets/scaffold.css
193
+ create app/assets/stylesheets/scaffold.css
194
194
  </shell>
195
195
 
196
196
  Looking at this output, it's easy to understand how generators work in Rails 3.0 and above. The scaffold generator doesn't actually generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.
@@ -319,7 +319,7 @@ If you generate another resource, you can see that we get exactly the same resul
319
319
 
320
320
  h3. Adding Generators Fallbacks
321
321
 
322
- One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit like "shoulda":http://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just wants to overwrite part of it, there is no need for shoulda to reimplement some generators again, it can simply tell Rails to use a +TestUnit+ generator if none was found under the +Shoulda+ namespace.
322
+ One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit like "shoulda":https://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just wants to overwrite part of it, there is no need for shoulda to reimplement some generators again, it can simply tell Rails to use a +TestUnit+ generator if none was found under the +Shoulda+ namespace.
323
323
 
324
324
  We can easily simulate this behavior by changing our +config/application.rb+ once again:
325
325
 
@@ -345,7 +345,7 @@ $ rails generate scaffold Comment body:text
345
345
  invoke shoulda
346
346
  create test/unit/comment_test.rb
347
347
  create test/fixtures/comments.yml
348
- route map.resources :comments
348
+ route resources :comments
349
349
  invoke scaffold_controller
350
350
  create app/controllers/comments_controller.rb
351
351
  invoke erb
@@ -371,24 +371,24 @@ h3. Application templates
371
371
  Now that you've seen how generators can be used _inside_ an application, did you know they can also be used to _generate_ applications too? This kind of generator is referred as a "template".
372
372
 
373
373
  <ruby>
374
- gem("rspec-rails", :group => "test")
375
- gem("cucumber-rails", :group => "test")
374
+ gem("rspec-rails", :group => "test")
375
+ gem("cucumber-rails", :group => "test")
376
376
 
377
- if yes?("Would you like to install Devise?")
378
- gem("devise")
379
- generate("devise:install")
380
- model_name = ask("What would you like the user model to be called? [user]")
381
- model_name = "user" if model_name.blank?
382
- generate("devise", model_name)
383
- end
377
+ if yes?("Would you like to install Devise?")
378
+ gem("devise")
379
+ generate("devise:install")
380
+ model_name = ask("What would you like the user model to be called? [user]")
381
+ model_name = "user" if model_name.blank?
382
+ generate("devise", model_name)
383
+ end
384
384
  </ruby>
385
385
 
386
- In the above template we specify that the application relies on the +rspec-rails+ and +cucumber-rails+ gem so these two will be added to the +test+ group in the +Gemfile+. Then we pose a question to the user about whether or not they would like to install Devise. If the user replies "y" or "yes" to this question, then the template will add Devise to the +Gemfile+ outside of any group and then runs the +devise:install+ generator. This template then takes the users input and runs the +devise+ generator, with the user's answer from the last question being passed to this generator.
386
+ In the above template we specify that the application relies on the +rspec-rails+ and +cucumber-rails+ gem so these two will be added to the +test+ group in the +Gemfile+. Then we pose a question to the user about whether or not they would like to install Devise. If the user replies "y" or "yes" to this question, then the template will add Devise to the +Gemfile+ outside of any group and then runs the +devise:install+ generator. This template then takes the users input and runs the +devise+ generator, with the user's answer from the last question being passed to this generator.
387
387
 
388
388
  Imagine that this template was in a file called +template.rb+. We can use it to modify the outcome of the +rails new+ command by using the +-m+ option and passing in the filename:
389
389
 
390
390
  <shell>
391
- rails new thud -m template.rb
391
+ $ rails new thud -m template.rb
392
392
  </shell>
393
393
 
394
394
  This command will generate the +Thud+ application, and then apply the template to the generated output.
@@ -396,14 +396,14 @@ This command will generate the +Thud+ application, and then apply the template t
396
396
  Templates don't have to be stored on the local system, the +-m+ option also supports online templates:
397
397
 
398
398
  <shell>
399
- rails new thud -m https://gist.github.com/722911
399
+ $ rails new thud -m https://gist.github.com/722911.txt
400
400
  </shell>
401
401
 
402
402
  Whilst the final section of this guide doesn't cover how to generate the most awesome template known to man, it will take you through the methods available at your disposal so that you can develop it yourself. These same methods are also available for generators.
403
403
 
404
404
  h3. Generator methods
405
405
 
406
- The following are methods available for both generators and templates for Rails.
406
+ The following are methods available for both generators and templates for Rails.
407
407
 
408
408
  NOTE: Methods provided by Thor are not covered this guide and can be found in "Thor's documentation":http://rdoc.info/github/wycats/thor/master/Thor/Actions.html
409
409
 
@@ -428,8 +428,8 @@ h4. +gem+
428
428
  Specifies a gem dependency of the application.
429
429
 
430
430
  <ruby>
431
- gem("rspec", :group => "test", :version => "2.1.0")
432
- gem("devise", "1.1.5")
431
+ gem("rspec", :group => "test", :version => "2.1.0")
432
+ gem("devise", "1.1.5")
433
433
  </ruby>
434
434
 
435
435
  Available options are:
@@ -470,10 +470,9 @@ Adds a line to +config/application.rb+ directly after the application class defi
470
470
  This method can also take a block:
471
471
 
472
472
  <ruby>
473
- application do
474
- "config.asset_host = 'http://example.com'"
475
- end
476
- end
473
+ application do
474
+ "config.asset_host = 'http://example.com'"
475
+ end
477
476
  </ruby>
478
477
 
479
478
  Available options are:
@@ -481,9 +480,9 @@ Available options are:
481
480
  * +:env+ - Specify an environment for this configuration option. If you wish to use this option with the block syntax the recommended syntax is as follows:
482
481
 
483
482
  <ruby>
484
- application(nil, :env => "development") do
485
- "config.asset_host = 'http://localhost:3000'"
486
- end
483
+ application(nil, :env => "development") do
484
+ "config.asset_host = 'http://localhost:3000'"
485
+ end
487
486
  </ruby>
488
487
 
489
488
  h4. +git+
@@ -526,9 +525,9 @@ Places a file into +lib+ which contains the specified code.
526
525
  This method also takes a block:
527
526
 
528
527
  <ruby>
529
- lib("super_special.rb") do
530
- puts "Super special!"
531
- end
528
+ lib("super_special.rb") do
529
+ puts "Super special!"
530
+ end
532
531
  </ruby>
533
532
 
534
533
  h4. +rakefile+
@@ -542,13 +541,13 @@ Creates a Rake file in the +lib/tasks+ directory of the application.
542
541
  This method also takes a block:
543
542
 
544
543
  <ruby>
545
- rakefile("test.rake") do
546
- %Q{
547
- task :rock => :environment do
548
- puts "Rockin'"
549
- end
550
- }
551
- end
544
+ rakefile("test.rake") do
545
+ %Q{
546
+ task :rock => :environment do
547
+ puts "Rockin'"
548
+ end
549
+ }
550
+ end
552
551
  </ruby>
553
552
 
554
553
  h4. +initializer+
@@ -562,9 +561,9 @@ Creates an initializer in the +config/initializers+ directory of the application
562
561
  This method also takes a block:
563
562
 
564
563
  <ruby>
565
- initializer("begin.rb") do
566
- puts "Almost done!"
567
- end
564
+ initializer("begin.rb") do
565
+ puts "Almost done!"
566
+ end
568
567
  </ruby>
569
568
 
570
569
  h4. +generate+