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
@@ -10,20 +10,20 @@ Guides are written in "Textile":http://www.textism.com/tools/textile/. There's c
10
10
 
11
11
  h3. Prologue
12
12
 
13
- Each guide should start with motivational text at the top. That's the little introduction in the blue area. The prologue should tell the readers what's the guide about, and what will they learn. See for example the "Routing Guide":routing.html.
13
+ Each guide should start with motivational text at the top (that's the little introduction in the blue area.) The prologue should tell the reader what the guide is about, and what they will learn. See for example the "Routing Guide":routing.html.
14
14
 
15
15
  h3. Titles
16
16
 
17
17
  The title of every guide uses +h2+, guide sections use +h3+, subsections +h4+, etc.
18
18
 
19
- Capitalize all words except for internal articles, prepositions, conjuctions, and forms of the verb to be:
19
+ Capitalize all words except for internal articles, prepositions, conjunctions, and forms of the verb to be:
20
20
 
21
21
  <plain>
22
22
  h5. Middleware Stack is an Array
23
23
  h5. When are Objects Saved?
24
24
  </plain>
25
25
 
26
- Use same typography as in regular text:
26
+ Use the same typography as in regular text:
27
27
 
28
28
  <plain>
29
29
  h6. The +:content_type+ Option
@@ -42,29 +42,35 @@ Those guidelines apply also to guides.
42
42
 
43
43
  h3. HTML Generation
44
44
 
45
- To generate all the guides just cd into the +railties+ directory and execute
45
+ To generate all the guides, just +cd+ into the +railties+ directory and execute:
46
46
 
47
47
  <plain>
48
- rake generate_guides
48
+ bundle exec rake generate_guides
49
49
  </plain>
50
50
 
51
- You'll need the gems erubis, i18n, and RedCloth.
51
+ (You may need to run +bundle install+ first to install the required gems.)
52
52
 
53
53
  To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable:
54
54
 
55
55
  <plain>
56
- rake generate_guides ONLY=my_guide
56
+ bundle exec rake generate_guides ONLY=my_guide
57
57
  </plain>
58
58
 
59
- Although by default guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
59
+ By default, guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
60
60
 
61
- To force process of al the guides pass +ALL=1+.
61
+ To force process of all the guides, pass +ALL=1+.
62
62
 
63
- It is also recommended that you work with +WARNINGS=1+, this detects duplicate IDs and warns about broken internal links.
63
+ It is also recommended that you work with +WARNINGS=1+. This detects duplicate IDs and warns about broken internal links.
64
64
 
65
- h3. HTML validation
65
+ If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +LANGUAGE+ environment variable:
66
66
 
67
- Please do validate the generated HTML with
67
+ <plain>
68
+ rake generate_guides LANGUAGE=es
69
+ </plain>
70
+
71
+ h3. HTML Validation
72
+
73
+ Please validate the generated HTML with:
68
74
 
69
75
  <plain>
70
76
  rake validate_guides
@@ -74,4 +80,5 @@ Particularly, titles get an ID generated from their content and this often leads
74
80
 
75
81
  h3. Changelog
76
82
 
83
+ * March 31, 2011: grammar tweaks by "Josiah Ivey":http://twitter.com/josiahivey
77
84
  * October 5, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn
@@ -57,7 +57,11 @@ Many web applications have an authentication system: a user provides a user name
57
57
 
58
58
  Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
59
59
 
60
- * Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_.
60
+ * Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file:
61
+
62
+ <ruby>
63
+ config.force_ssl = true
64
+ </ruby>
61
65
 
62
66
  * Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a _(highlight)log-out button_ in the web application, and _(highlight)make it prominent_.
63
67
 
@@ -143,7 +147,7 @@ reset_session
143
147
 
144
148
  If you use the popular RestfulAuthentication plugin for user management, add reset_session to the SessionsController#create action. Note that this removes any value from the session, _(highlight)you have to transfer them to the new session_.
145
149
 
146
- Another countermeasure is to _(highlight)save user-specific properties in the session_, verify them every time a request comes in, and deny access, if the information does not match. Such properties could be the remote IP address or the user agent (the web browser name), though the latter is less user-specific. When saving the IP address, you have to bear in mind that there are Internet service providers or large organizations that put their users behind proxies. _(highlight)These might change over the course of a session_, so these users will not be able to use your application, or only in a limited way.
150
+ Another countermeasure is to _(highlight)save user-specific properties in the session_, verify them every time a request comes in, and deny access, if the information does not match. Such properties could be the remote IP address or the user agent (the web browser name), though the latter is less user-specific. When saving the IP address, you have to bear in mind that there are Internet service providers or large organizations that put their users behind proxies. _(highlight)These might change over the course of a session_, so these users will not be able to use your application, or only in a limited way.
147
151
 
148
152
  h4. Session Expiry
149
153
 
@@ -207,15 +211,7 @@ The HTTP protocol basically provides two main types of requests - GET and POST (
207
211
 
208
212
  If your web application is RESTful, you might be used to additional HTTP verbs, such as PUT or DELETE. Most of today‘s web browsers, however do not support them - only GET and POST. Rails uses a hidden +_method+ field to handle this barrier.
209
213
 
210
- _(highlight)The verify method in a controller can make sure that specific actions may not be used over GET_. Here is an example to verify the use of the transfer action over POST. If the action comes in using any other verb, it redirects to the list action.
211
-
212
- <ruby>
213
- verify :method => :post, :only => [:transfer], :redirect_to => {:action => :list}
214
- </ruby>
215
-
216
- With this precaution, the attack from above will not work, because the browser sends a GET request for images, which will not be accepted by the web application.
217
-
218
- But this was only the first step, because _(highlight)POST requests can be sent automatically, too_. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request.
214
+ _(highlight)POST requests can be sent automatically, too_. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request.
219
215
 
220
216
  <html>
221
217
  <a href="http://www.harmless.com/" onclick="
@@ -234,13 +230,13 @@ Or the attacker places the code into the onmouseover event handler of an image:
234
230
  <img src="http://www.harmless.com/img" width="400" height="400" onmouseover="..." />
235
231
  </html>
236
232
 
237
- There are many other possibilities, including Ajax to attack the victim in the background.
The _(highlight)solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:
233
+ There are many other possibilities, including Ajax to attack the victim in the background.
The _(highlight)solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:
238
234
 
239
235
  <ruby>
240
236
  protect_from_forgery :secret => "123456789012345678901234567890..."
241
237
  </ruby>
242
238
 
243
- This will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. It will raise an ActionController::InvalidAuthenticityToken error, if the security token doesn't match what was expected.
239
+ This will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. If the security token doesn't match what was expected, the session will be reset. *Note:* In Rails versions prior to 3.0.4, this raised an <tt>ActionController::InvalidAuthenticityToken</tt> error.
244
240
 
245
241
  Note that _(highlight)cross-site scripting (XSS) vulnerabilities bypass all CSRF protections_. XSS gives the attacker access to all elements on a page, so he can read the CSRF security token from a form or directly submit the form. Read <a href="#cross-site-scripting-xss">more about XSS</a> later.
246
242
 
@@ -282,7 +278,7 @@ h4. File Uploads
282
278
 
283
279
  Many web applications allow users to upload files. _(highlight)File names, which the user may choose (partly), should always be filtered_ as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like “../../../etc/passwd”, it may overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so – one more reason to run web servers, database servers and other programs as a less privileged Unix user.
284
280
 
285
- When filtering user input file names, _(highlight)don't try to remove malicious parts_. Think of a situation where the web application removes all “../” in a file name and an attacker uses a string such as “....//” - the result will be “../”. It is best to use a whitelist approach, which _(highlight)checks for the validity of a file name with a set of accepted characters_. This is opposed to a blacklist approach which attempts to remove not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the "attachment_fu plugin":http://github.com/technoweenie/attachment_fu/tree/master:
281
+ When filtering user input file names, _(highlight)don't try to remove malicious parts_. Think of a situation where the web application removes all “../” in a file name and an attacker uses a string such as “....//” - the result will be “../”. It is best to use a whitelist approach, which _(highlight)checks for the validity of a file name with a set of accepted characters_. This is opposed to a blacklist approach which attempts to remove not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the "attachment_fu plugin":https://github.com/technoweenie/attachment_fu/tree/master:
286
282
 
287
283
  <ruby>
288
284
  def sanitize_filename(filename)
@@ -390,7 +386,7 @@ params[:user] # => {:name => “ow3ned”, :admin => true}
390
386
 
391
387
  So if you create a new user using mass-assignment, it may be too easy to become an administrator.
392
388
 
393
- Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
389
+ Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
394
390
 
395
391
  <ruby>
396
392
  class Person < ActiveRecord::Base
@@ -414,10 +410,17 @@ To avoid this, Rails provides two class methods in your Active Record class to c
414
410
  attr_protected :admin
415
411
  </ruby>
416
412
 
413
+ +attr_protected+ also optionally takes a scope option using :as which allows you to define multiple mass-assignment groupings. If no scope is defined then attributes will be added to the default group.
414
+
415
+ <ruby>
416
+ attr_protected :last_login, :as => :admin
417
+ </ruby>
418
+
417
419
  A much better way, because it follows the whitelist-principle, is the +attr_accessible+ method. It is the exact opposite of +attr_protected+, because _(highlight)it takes a list of attributes that will be accessible_. All other attributes will be protected. This way you won't forget to protect attributes when adding new ones in the course of development. Here is an example:
418
420
 
419
421
  <ruby>
420
422
  attr_accessible :name
423
+ attr_accessible :name, :is_admin, :as => :admin
421
424
  </ruby>
422
425
 
423
426
  If you want to set a protected attribute, you will to have to assign it individually:
@@ -430,13 +433,43 @@ params[:user] # => {:name => "ow3ned", :admin => true}
430
433
  @user.admin # => true
431
434
  </ruby>
432
435
 
433
- A more paranoid technique to protect your whole project would be to enforce that all models whitelist their accessible attributes. This can be easily achieved with a very simple initializer:
436
+ When assigning attributes in Active Record using +attributes=+, or +update_attributes+ the :default scope will be used. To assign attributes using different scopes you should use +assign_attributes+ which accepts an optional :as options parameter. If no :as option is provided then the :default scope will be used. You can also bypass mass-assignment security by using the +:without_protection+ option. Here is an example:
434
437
 
435
438
  <ruby>
436
- ActiveRecord::Base.send(:attr_accessible, nil)
439
+ @user = User.new
440
+
441
+ @user.assign_attributes({ :name => 'Josh', :is_admin => true })
442
+ @user.name # => Josh
443
+ @user.is_admin # => false
444
+
445
+ @user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
446
+ @user.name # => Josh
447
+ @user.is_admin # => true
448
+
449
+ @user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
450
+ @user.name # => Josh
451
+ @user.is_admin # => true
437
452
  </ruby>
438
453
 
439
- This will create an empty whitelist of attributes available for mass assignment for all models in your app. As such, your models will need to explicitly whitelist accessible parameters by using an +attr_accessible+ declaration. This technique is best applied at the start of a new project. However, for an existing project with a thorough set of functional tests, it should be straightforward and relatively quick to insert this initializer, run your tests, and expose each attribute (via +attr_accessible+) as dictated by your failing tests.
454
+ In a similar way, +new+, +create+ and <tt>create!</tt> methods respect mass-assignment security and accepts either +:as+ or +:without_protection+ options. For example:
455
+
456
+ <ruby>
457
+ @user = User.new({ :name => 'Sebastian', :is_admin => true }, :as => :admin)
458
+ @user.name # => Sebastian
459
+ @user.is_admin # => true
460
+
461
+ @user = User.create({ :name => 'Sebastian', :is_admin => true }, :without_protection => true)
462
+ @user.name # => Sebastian
463
+ @user.is_admin # => true
464
+ </ruby>
465
+
466
+ A more paranoid technique to protect your whole project would be to enforce that all models define their accessible attributes. This can be easily achieved with a very simple application config option of:
467
+
468
+ <ruby>
469
+ config.active_record.whitelist_attributes = true
470
+ </ruby>
471
+
472
+ This will create an empty whitelist of attributes available for mass-assignment for all models in your app. As such, your models will need to explicitly whitelist or blacklist accessible parameters by using an +attr_accessible+ or +attr_protected+ declaration. This technique is best applied at the start of a new project. However, for an existing project with a thorough set of functional tests, it should be straightforward and relatively quick to use this application config option; run your tests, and expose each attribute (via +attr_accessible+ or +attr_protected+) as dictated by your failing tests.
440
473
 
441
474
  h3. User Management
442
475
 
@@ -550,7 +583,7 @@ Ruby uses a slightly different approach than many other languages to match the e
550
583
 
551
584
  <ruby>
552
585
  class File < ActiveRecord::Base
553
- validates_format_of :name, :with => /^[\w\.\-\+]+$/
586
+ validates :name, :format => /^[\w\.\-\+]+$/
554
587
  end
555
588
  </ruby>
556
589
 
@@ -616,7 +649,7 @@ h5(#sql-injection-introduction). Introduction
616
649
  SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query:
617
650
 
618
651
  <ruby>
619
- Project.find(:all, :conditions => "name = '#{params[:name]}'")
652
+ Project.all(:conditions => "name = '#{params[:name]}'")
620
653
  </ruby>
621
654
 
622
655
  This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters ' OR 1 --, the resulting SQL query will be:
@@ -632,7 +665,7 @@ h5. Bypassing Authorization
632
665
  Usually a web application includes access control. The user enters his login credentials, the web application tries to find the matching record in the users table. The application grants access when it finds a record. However, an attacker may possibly bypass this check with SQL injection. The following shows a typical database query in Rails to find the first record in the users table which matches the login credentials parameters supplied by the user.
633
666
 
634
667
  <ruby>
635
- User.find(:first, "login = '#{params[:name]}' AND password = '#{params[:password]}'")
668
+ User.first("login = '#{params[:name]}' AND password = '#{params[:password]}'")
636
669
  </ruby>
637
670
 
638
671
  If an attacker enters ' OR '1'='1 as the name, and ' OR '2'>'1 as the password, the resulting SQL query will be:
@@ -648,7 +681,7 @@ h5. Unauthorized Reading
648
681
  The UNION statement connects two SQL queries and returns the data in one set. An attacker can use it to read arbitrary data from the database. Let's take the example from above:
649
682
 
650
683
  <ruby>
651
- Project.find(:all, :conditions => "name = '#{params[:name]}'")
684
+ Project.all(:conditions => "name = '#{params[:name]}'")
652
685
  </ruby>
653
686
 
654
687
  And now let's inject another query using the UNION statement:
@@ -675,13 +708,13 @@ Ruby on Rails has a built-in filter for special SQL characters, which will escap
675
708
  Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this:
676
709
 
677
710
  <ruby>
678
- Model.find(:first, :conditions => ["login = ? AND password = ?", entered_user_name, entered_password])
711
+ Model.first(:conditions => ["login = ? AND password = ?", entered_user_name, entered_password])
679
712
  </ruby>
680
713
 
681
714
  As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result:
682
715
 
683
716
  <ruby>
684
- Model.find(:first, :conditions => {:login => entered_user_name, :password => entered_password})
717
+ Model.first(:conditions => {:login => entered_user_name, :password => entered_password})
685
718
  </ruby>
686
719
 
687
720
  The array or hash form is only available in model instances. You can try +sanitize_sql()+ elsewhere. _(highlight)Make it a habit to think about the security consequences when using an external string in SQL_.
@@ -889,12 +922,6 @@ h4. Ajax Injection
889
922
 
890
923
  If you use the "in_place_editor plugin":http://dev.rubyonrails.org/browser/plugins/in_place_editing, or actions that return a string, rather than rendering a view, _(highlight)you have to escape the return value in the action_. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method.
891
924
 
892
- h4. RJS Injection
893
-
894
- -- _Don't forget to escape in JavaScript (RJS) templates, too._
895
-
896
- The RJS API generates blocks of JavaScript code based on Ruby code, thus allowing you to manipulate a view or parts of a view from the server side. <em class="highlight">If you allow user input in RJS templates, do escape it using +escape_javascript()+ within JavaScript functions, and in HTML parts using +h()+</em>. Otherwise an attacker could execute arbitrary JavaScript.
897
-
898
925
  h4. Command Line Injection
899
926
 
900
927
  -- _Use user-supplied command line parameters with caution._
@@ -79,9 +79,9 @@ steve:
79
79
 
80
80
  Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are separated by a blank space. You can place comments in a fixture file by using the # character in the first column.
81
81
 
82
- h5. ERb'in It Up
82
+ h5. ERB'in It Up
83
83
 
84
- ERb allows you embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data.
84
+ ERB allows you to embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERB when you load fixtures. This allows you to use Ruby to help you generate some sample data.
85
85
 
86
86
  <erb>
87
87
  <% earth_size = 20 %>
@@ -227,15 +227,15 @@ $ rake db:migrate
227
227
  $ rake db:test:load
228
228
  </shell>
229
229
 
230
- Above +rake db:migrate+ runs any pending migrations on the _development_ environment and updates +db/schema.rb+. +rake db:test:load+ recreates the test database from the current +db/schema.rb+. On subsequent attempts, it is a good idea to first run +db:test:prepare+, as it first checks for pending migrations and warns you appropriately.
230
+ The +rake db:migrate+ above runs any pending migrations on the _development_ environment and updates +db/schema.rb+. The +rake db:test:load+ recreates the test database from the current +db/schema.rb+. On subsequent attempts, it is a good idea to first run +db:test:prepare+, as it first checks for pending migrations and warns you appropriately.
231
231
 
232
- NOTE: +db:test:prepare+ will fail with an error if +db/schema.rb+ doesn't exists.
232
+ NOTE: +db:test:prepare+ will fail with an error if +db/schema.rb+ doesn't exist.
233
233
 
234
234
  h5. Rake Tasks for Preparing your Application for Testing
235
235
 
236
236
  |_.Tasks |_.Description|
237
237
  |+rake db:test:clone+ |Recreate the test database from the current environment's database schema|
238
- |+rake db:test:clone_structure+ |Recreate the test databases from the development structure|
238
+ |+rake db:test:clone_structure+ |Recreate the test database from the development structure|
239
239
  |+rake db:test:load+ |Recreate the test database from the current +schema.rb+|
240
240
  |+rake db:test:prepare+ |Check for pending migrations and load the test schema|
241
241
  |+rake db:test:purge+ |Empty the test database.|
@@ -262,7 +262,7 @@ This will run all the test methods from the test case. Note that +test_helper.rb
262
262
  You can also run a particular test method from the test case by using the +-n+ switch with the +test method name+.
263
263
 
264
264
  <shell>
265
- $ ruby -Itest test/unit/post_test.rb -n test_truth
265
+ $ ruby -Itest test/unit/post_test.rb -n test_the_truth
266
266
 
267
267
  Loaded suite unit/post_test
268
268
  Started
@@ -321,7 +321,7 @@ Now to get this test to pass we can add a model level validation for the _title_
321
321
 
322
322
  <ruby>
323
323
  class Post < ActiveRecord::Base
324
- validates_presence_of :title
324
+ validates :title, :presence => true
325
325
  end
326
326
  </ruby>
327
327
 
@@ -391,7 +391,7 @@ There are a bunch of different types of assertions you can use. Here's the compl
391
391
  |+assert_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is true.|
392
392
  |+assert_not_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is false.|
393
393
  |+assert_match( regexp, string, [msg] )+ |Ensures that a string matches the regular expression.|
394
- |+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't matches the regular expression.|
394
+ |+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't match the regular expression.|
395
395
  |+assert_in_delta( expecting, actual, delta, [msg] )+ |Ensures that the numbers +expecting+ and +actual+ are within +delta+ of each other.|
396
396
  |+assert_throws( symbol, [msg] ) { block }+ |Ensures that the given block throws the symbol.|
397
397
  |+assert_raise( exception1, exception2, ... ) { block }+ |Ensures that the given block raises one of the given exceptions.|
@@ -415,8 +415,8 @@ NOTE: +assert_valid(record)+ has been deprecated. Please use +assert(record.vali
415
415
 
416
416
  |_.Assertion |_.Purpose|
417
417
  |+assert_valid(record)+ |Ensures that the passed record is valid by Active Record standards and returns any error messages if it is not.|
418
- |+assert_difference(expressions, difference = 1, message = nil) {...}+ |Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
419
- |+assert_no_difference(expressions, message = nil, &amp;block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
418
+ |+assert_difference(expressions, difference = 1, message = nil) {...}+ |Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
419
+ |+assert_no_difference(expressions, message = nil, &amp;block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
420
420
  |+assert_recognizes(expected_options, path, extras={}, message=nil)+ |Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|
421
421
  |+assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)+ |Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.|
422
422
  |+assert_response(type, message = nil)+ |Asserts that the response comes with a specific status code. You can specify +:success+ to indicate 200, +:redirect+ to indicate 300-399, +:missing+ to indicate 404, or +:error+ to match the 500-599 range|
@@ -500,6 +500,8 @@ If you're familiar with the HTTP protocol, you'll know that +get+ is a type of r
500
500
 
501
501
  All of request types are methods that you can use, however, you'll probably end up using the first two more often than the others.
502
502
 
503
+ NOTE: Functional tests do not verify whether the specified request type should be accepted by the action. Request types in this context exist to make your tests more descriptive.
504
+
503
505
  h4. The Four Hashes of the Apocalypse
504
506
 
505
507
  After a request has been made by using one of the 5 methods (+get+, +post+, etc.) and processed, you will have 4 Hash objects ready for use:
@@ -512,12 +514,12 @@ After a request has been made by using one of the 5 methods (+get+, +post+, etc.
512
514
  As is the case with normal Hash objects, you can access the values by referencing the keys by string. You can also reference them by symbol name, except for +assigns+. For example:
513
515
 
514
516
  <ruby>
515
- flash["gordon"] flash[:gordon]
516
- session["shmession"] session[:shmession]
517
- cookies["are_good_for_u"] cookies[:are_good_for_u]
517
+ flash["gordon"] flash[:gordon]
518
+ session["shmession"] session[:shmession]
519
+ cookies["are_good_for_u"] cookies[:are_good_for_u]
518
520
 
519
521
  # Because you can't use assigns[:something] for historical reasons:
520
- assigns["something"] assigns(:something)
522
+ assigns["something"] assigns(:something)
521
523
  </ruby>
522
524
 
523
525
  h4. Instance Variables Available
@@ -582,7 +584,7 @@ assert_select "ol" do
582
584
  end
583
585
  </ruby>
584
586
 
585
- The +assert_select+ assertion is quite powerful. For more advanced usage, refer to its "documentation":http://api.rubyonrails.org/classes/ActionController/Assertions/SelectorAssertions.html.
587
+ The +assert_select+ assertion is quite powerful. For more advanced usage, refer to its "documentation":http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html.
586
588
 
587
589
  h5. Additional View-Based Assertions
588
590
 
@@ -590,7 +592,6 @@ There are more assertions that are primarily used in testing views:
590
592
 
591
593
  |_.Assertion |_.Purpose|
592
594
  |+assert_select_email+ |Allows you to make assertions on the body of an e-mail. |
593
- |+assert_select_rjs+ |Allows you to make assertions on an RJS response. +assert_select_rjs+ has variants which allow you to narrow down on the updated element or even a particular operation on an element.|
594
595
  |+assert_select_encoded+ |Allows you to make assertions on encoded HTML. It does this by un-encoding the contents of each element and then calling the block with all the un-encoded elements.|
595
596
  |+css_select(selector)+ or +css_select(element, selector)+ |Returns an array of all the elements selected by the _selector_. In the second variant it first matches the base _element_ and tries to match the _selector_ expression on any of its children. If there are no matches both variants return an empty array.|
596
597
 
@@ -619,7 +620,7 @@ Here's what a freshly-generated integration test looks like:
619
620
  <ruby>
620
621
  require 'test_helper'
621
622
 
622
- class UserFlowsTest < ActionController::IntegrationTest
623
+ class UserFlowsTest < ActionDispatch::IntegrationTest
623
624
  fixtures :all
624
625
 
625
626
  # Replace this with your real tests.
@@ -629,7 +630,7 @@ class UserFlowsTest < ActionController::IntegrationTest
629
630
  end
630
631
  </ruby>
631
632
 
632
- Integration tests inherit from +ActionController::IntegrationTest+. This makes available some additional helpers to use in your integration tests. Also you need to explicitly include the fixtures to be made available to the test.
633
+ Integration tests inherit from +ActionDispatch::IntegrationTest+. This makes available some additional helpers to use in your integration tests. Also you need to explicitly include the fixtures to be made available to the test.
633
634
 
634
635
  h4. Helpers Available for Integration Tests
635
636
 
@@ -655,7 +656,7 @@ A simple integration test that exercises multiple controllers:
655
656
  <ruby>
656
657
  require 'test_helper'
657
658
 
658
- class UserFlowsTest < ActionController::IntegrationTest
659
+ class UserFlowsTest < ActionDispatch::IntegrationTest
659
660
  fixtures :users
660
661
 
661
662
  test "login and browse site" do
@@ -683,7 +684,7 @@ Here's an example of multiple sessions and custom DSL in an integration test
683
684
  <ruby>
684
685
  require 'test_helper'
685
686
 
686
- class UserFlowsTest < ActionController::IntegrationTest
687
+ class UserFlowsTest < ActionDispatch::IntegrationTest
687
688
  fixtures :users
688
689
 
689
690
  test "login and browse site" do
@@ -740,13 +741,14 @@ You don't need to set up and run your tests by hand on a test-by-test basis. Rai
740
741
  |+rake test:plugins+ |Run all the plugin tests from +vendor/plugins/*/**/test+ (or specify with +PLUGIN=_name_+)|
741
742
  |+rake test:profile+ |Profile the performance tests|
742
743
  |+rake test:recent+ |Tests recent changes|
743
- |+rake test:uncommitted+ |Runs all the tests which are uncommitted. Only supports Subversion|
744
+ |+rake test:uncommitted+ |Runs all the tests which are uncommitted. Supports Subversion and Git|
744
745
  |+rake test:units+ |Runs all the unit tests from +test/unit+|
745
746
 
746
747
 
747
748
  h3. Brief Note About +Test::Unit+
748
749
 
749
- Ruby ships with a boat load of libraries. One little gem of a library is +Test::Unit+, a framework for unit testing in Ruby. All the basic assertions discussed above are actually defined in +Test::Unit::Assertions+. The class +ActiveSupport::TestCase+ which we have been using in our unit and functional tests extends +Test::Unit::TestCase+ that it is how we can use all the basic assertions in our tests.
750
+ Ruby ships with a boat load of libraries. One little gem of a library is +Test::Unit+, a framework for unit testing in Ruby. All the basic assertions discussed above are actually defined in +Test::Unit::Assertions+. The class +ActiveSupport::TestCase+ which we have been using in our unit and functional tests extends +Test::Unit::TestCase+, allowing
751
+ us to use all of the basic assertions in our tests.
750
752
 
751
753
  NOTE: For more information on +Test::Unit+, refer to "test/unit Documentation":http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/
752
754
 
@@ -939,8 +941,8 @@ h3. Other Testing Approaches
939
941
  The built-in +test/unit+ based testing is not the only way to test Rails applications. Rails developers have come up with a wide variety of other approaches and aids for testing, including:
940
942
 
941
943
  * "NullDB":http://avdi.org/projects/nulldb/, a way to speed up testing by avoiding database use.
942
- * "Factory Girl":http://github.com/thoughtbot/factory_girl/tree/master, as replacement for fixtures.
943
- * "Machinist":http://github.com/notahat/machinist/tree/master, another replacement for fixtures.
944
+ * "Factory Girl":https://github.com/thoughtbot/factory_girl/tree/master, a replacement for fixtures.
945
+ * "Machinist":https://github.com/notahat/machinist/tree/master, another replacement for fixtures.
944
946
  * "Shoulda":http://www.thoughtbot.com/projects/shoulda, an extension to +test/unit+ with additional helpers, macros, and assertions.
945
947
  * "RSpec":http://rspec.info/, a behavior-driven development framework
946
948
 
@@ -21,7 +21,7 @@
21
21
  #
22
22
  # Separate many using commas:
23
23
  #
24
- # # validates only
24
+ # # validates only association_basics.html and migrations.html
25
25
  # ONLY=assoc,migrations rake validate_guides
26
26
  #
27
27
  # ---------------------------------------------------------------------------
@@ -88,4 +88,4 @@ module RailsGuides
88
88
  end
89
89
  end
90
90
 
91
- RailsGuides::Validator.new.validate
91
+ RailsGuides::Validator.new.validate