rails 4.1.0.beta2 → 4.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/images/getting_started/challenge.png +0 -0
- data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
- data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
- data/guides/assets/images/getting_started/form_with_errors.png +0 -0
- data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
- data/guides/assets/images/getting_started/new_article.png +0 -0
- data/guides/assets/images/getting_started/rails_welcome.jpg +0 -0
- data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
- data/guides/assets/images/getting_started/{show_action_for_posts.png → show_action_for_articles.png} +0 -0
- data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
- data/guides/bug_report_templates/action_controller_gem.rb +5 -2
- data/guides/bug_report_templates/active_record_gem.rb +4 -1
- data/guides/code/getting_started/Gemfile +20 -23
- data/guides/code/getting_started/Gemfile.lock +73 -67
- data/guides/code/getting_started/app/views/layouts/application.html.erb +2 -2
- data/guides/code/getting_started/config/environments/production.rb +2 -2
- data/guides/code/getting_started/config/environments/test.rb +1 -1
- data/guides/rails_guides/helpers.rb +2 -0
- data/guides/source/3_0_release_notes.md +1 -1
- data/guides/source/4_1_release_notes.md +181 -61
- data/guides/source/action_controller_overview.md +46 -7
- data/guides/source/action_mailer_basics.md +5 -5
- data/guides/source/active_record_querying.md +18 -18
- data/guides/source/active_record_validations.md +11 -9
- data/guides/source/active_support_core_extensions.md +13 -1
- data/guides/source/api_documentation_guidelines.md +52 -2
- data/guides/source/asset_pipeline.md +54 -22
- data/guides/source/association_basics.md +13 -0
- data/guides/source/configuring.md +159 -11
- data/guides/source/contributing_to_ruby_on_rails.md +7 -6
- data/guides/source/development_dependencies_install.md +2 -0
- data/guides/source/documents.yaml +1 -1
- data/guides/source/engines.md +4 -3
- data/guides/source/form_helpers.md +10 -3
- data/guides/source/getting_started.md +525 -478
- data/guides/source/i18n.md +4 -4
- data/guides/source/initialization.md +2 -2
- data/guides/source/layouts_and_rendering.md +38 -8
- data/guides/source/migrations.md +5 -5
- data/guides/source/plugins.md +0 -1
- data/guides/source/routing.md +4 -2
- data/guides/source/security.md +47 -4
- data/guides/source/testing.md +10 -31
- data/guides/source/upgrading_ruby_on_rails.md +121 -12
- data/guides/source/working_with_javascript_in_rails.md +1 -1
- metadata +23 -24
- data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
- data/guides/assets/images/getting_started/new_post.png +0 -0
- data/guides/assets/images/getting_started/post_with_comments.png +0 -0
- data/guides/assets/images/getting_started/rails_welcome.png +0 -0
- data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
- data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
data/guides/source/i18n.md
CHANGED
@@ -101,7 +101,7 @@ This means, that in the `:en` locale, the key _hello_ will map to the _Hello wor
|
|
101
101
|
|
102
102
|
The I18n library will use **English** as a **default locale**, i.e. if you don't set a different locale, `:en` will be used for looking up translations.
|
103
103
|
|
104
|
-
NOTE: The i18n library takes a **pragmatic approach** to locale keys (after [some discussion](http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en)), including only the _locale_ ("language") part, like `:en`, `:pl`, not the _region_ part, like `:en-US` or `:en-GB`, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as `:cs`, `:th` or `:es` (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the `:en-US` locale you would have $ as a currency symbol, while in `:en-GB`, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a `:en-GB` dictionary. Various [Rails I18n plugins](http://rails-i18n.org/wiki) such as [Globalize3](https://github.com/
|
104
|
+
NOTE: The i18n library takes a **pragmatic approach** to locale keys (after [some discussion](http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en)), including only the _locale_ ("language") part, like `:en`, `:pl`, not the _region_ part, like `:en-US` or `:en-GB`, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as `:cs`, `:th` or `:es` (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the `:en-US` locale you would have $ as a currency symbol, while in `:en-GB`, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a `:en-GB` dictionary. Various [Rails I18n plugins](http://rails-i18n.org/wiki) such as [Globalize3](https://github.com/globalize/globalize) may help you implement it.
|
105
105
|
|
106
106
|
The **translations load path** (`I18n.load_path`) is just a Ruby Array of paths to your translation files that will be loaded automatically and available in your application. You can pick whatever directory and translation file naming scheme makes sense for you.
|
107
107
|
|
@@ -214,7 +214,7 @@ This approach has almost the same set of advantages as setting the locale from t
|
|
214
214
|
|
215
215
|
Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus **passing it through the requests** is. To include an explicit option in every URL (e.g. `link_to( books_url(locale: I18n.locale))`) would be tedious and probably impossible, of course.
|
216
216
|
|
217
|
-
Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515, which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
|
217
|
+
Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515), which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
|
218
218
|
|
219
219
|
We can include something like this in our `ApplicationController` then:
|
220
220
|
|
@@ -824,7 +824,7 @@ This way you can provide special translations for various error messages at diff
|
|
824
824
|
|
825
825
|
The translated model name, translated attribute name, and value are always available for interpolation.
|
826
826
|
|
827
|
-
So, for example, instead of the default error message `"
|
827
|
+
So, for example, instead of the default error message `"cannot be blank"` you could use the attribute name like this : `"Please fill in your %{attribute}"`.
|
828
828
|
|
829
829
|
* `count`, where available, can be used for pluralization if present:
|
830
830
|
|
@@ -926,7 +926,7 @@ Customize your I18n Setup
|
|
926
926
|
|
927
927
|
### Using Different Backends
|
928
928
|
|
929
|
-
For several reasons the Simple backend shipped with Active Support only does the "simplest thing that could possibly work" _for Ruby on Rails_[^3] ... which means that it is only guaranteed to work for English and, as a side effect, languages that are very similar to English. Also, the simple backend is only capable of reading translations but
|
929
|
+
For several reasons the Simple backend shipped with Active Support only does the "simplest thing that could possibly work" _for Ruby on Rails_[^3] ... which means that it is only guaranteed to work for English and, as a side effect, languages that are very similar to English. Also, the simple backend is only capable of reading translations but cannot dynamically store them to any format.
|
930
930
|
|
931
931
|
That does not mean you're stuck with these limitations, though. The Ruby I18n gem makes it very easy to exchange the Simple backend implementation with something else that fits better for your needs. E.g. you could exchange it with Globalize's Static backend:
|
932
932
|
|
@@ -270,7 +270,7 @@ def parse_options(args)
|
|
270
270
|
options = default_options
|
271
271
|
|
272
272
|
# Don't evaluate CGI ISINDEX parameters.
|
273
|
-
# http://
|
273
|
+
# http://www.meb.uni-bonn.de/docs/cgi/cl.html
|
274
274
|
args.clear if ENV.include?("REQUEST_METHOD")
|
275
275
|
|
276
276
|
options.merge! opt_parser.parse! args
|
@@ -522,7 +522,7 @@ I18n and Rails configuration are all being defined here.
|
|
522
522
|
### Back to `config/environment.rb`
|
523
523
|
|
524
524
|
The rest of `config/application.rb` defines the configuration for the
|
525
|
-
`Rails::Application` which will be used once the application is fully
|
525
|
+
`Rails::Application` which will be used once the application is fully
|
526
526
|
initialized. When `config/application.rb` has finished loading Rails and defined
|
527
527
|
the application namespace, we go back to `config/environment.rb`,
|
528
528
|
where the application is initialized. For example, if the application was called
|
@@ -236,15 +236,34 @@ render inline: "xml.p {'Horrid coding practice!'}", type: :builder
|
|
236
236
|
|
237
237
|
#### Rendering Text
|
238
238
|
|
239
|
-
You can send plain text - with no markup at all - back to the browser by using
|
239
|
+
You can send plain text - with no markup at all - back to the browser by using
|
240
|
+
the `:plain` option to `render`:
|
240
241
|
|
241
242
|
```ruby
|
242
|
-
render
|
243
|
+
render plain: "OK"
|
243
244
|
```
|
244
245
|
|
245
|
-
TIP: Rendering pure text is most useful when you're responding to Ajax or web
|
246
|
+
TIP: Rendering pure text is most useful when you're responding to Ajax or web
|
247
|
+
service requests that are expecting something other than proper HTML.
|
246
248
|
|
247
|
-
NOTE: By default, if you use the `:
|
249
|
+
NOTE: By default, if you use the `:plain` option, the text is rendered without
|
250
|
+
using the current layout. If you want Rails to put the text into the current
|
251
|
+
layout, you need to add the `layout: true` option.
|
252
|
+
|
253
|
+
#### Rendering HTML
|
254
|
+
|
255
|
+
You can send a HTML string back to the browser by using the `:html` option to
|
256
|
+
`render`:
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
render html: "<strong>Not Found</strong>".html_safe
|
260
|
+
```
|
261
|
+
|
262
|
+
TIP: This is useful when you're rendering a small snippet of HTML code.
|
263
|
+
However, you might want to consider moving it to a template file if the markup
|
264
|
+
is complex.
|
265
|
+
|
266
|
+
NOTE: This option will escape HTML entities if the string is not html safe.
|
248
267
|
|
249
268
|
#### Rendering JSON
|
250
269
|
|
@@ -276,6 +295,19 @@ render js: "alert('Hello Rails');"
|
|
276
295
|
|
277
296
|
This will send the supplied string to the browser with a MIME type of `text/javascript`.
|
278
297
|
|
298
|
+
#### Rendering raw body
|
299
|
+
|
300
|
+
You can send a raw content back to the browser, without setting any content
|
301
|
+
type, by using the `:body` option to `render`:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
render body: "raw"
|
305
|
+
```
|
306
|
+
|
307
|
+
TIP: This option should be used only if you explicitly want the content type to
|
308
|
+
be unset. Using `:plain` or `:html` might be more appropriate in most of the
|
309
|
+
time.
|
310
|
+
|
279
311
|
#### Options for `render`
|
280
312
|
|
281
313
|
Calls to the `render` method generally accept four options:
|
@@ -1008,7 +1040,6 @@ You can also pass local variables into partials, making them even more powerful
|
|
1008
1040
|
|
1009
1041
|
```html+erb
|
1010
1042
|
<h1>New zone</h1>
|
1011
|
-
<%= error_messages_for :zone %>
|
1012
1043
|
<%= render partial: "form", locals: {zone: @zone} %>
|
1013
1044
|
```
|
1014
1045
|
|
@@ -1016,7 +1047,6 @@ You can also pass local variables into partials, making them even more powerful
|
|
1016
1047
|
|
1017
1048
|
```html+erb
|
1018
1049
|
<h1>Editing zone</h1>
|
1019
|
-
<%= error_messages_for :zone %>
|
1020
1050
|
<%= render partial: "form", locals: {zone: @zone} %>
|
1021
1051
|
```
|
1022
1052
|
|
@@ -1121,11 +1151,11 @@ With this change, you can access an instance of the `@products` collection as th
|
|
1121
1151
|
You can also pass in arbitrary local variables to any partial you are rendering with the `locals: {}` option:
|
1122
1152
|
|
1123
1153
|
```erb
|
1124
|
-
<%= render partial: "
|
1154
|
+
<%= render partial: "product", collection: @products,
|
1125
1155
|
as: :item, locals: {title: "Products Page"} %>
|
1126
1156
|
```
|
1127
1157
|
|
1128
|
-
|
1158
|
+
In this case, the partial will have access to a local variable `title` with the value "Products Page".
|
1129
1159
|
|
1130
1160
|
TIP: Rails also makes a counter variable available within a partial called by the collection, named after the member of the collection followed by `_counter`. For example, if you're rendering `@products`, within the partial you can refer to `product_counter` to tell you how many times the partial has been rendered. This does not work in conjunction with the `as: :value` option.
|
1131
1161
|
|
data/guides/source/migrations.md
CHANGED
@@ -297,10 +297,10 @@ You can append as many column name/type pairs as you want.
|
|
297
297
|
You can also specify some options just after the field type between curly
|
298
298
|
braces. You can use the following modifiers:
|
299
299
|
|
300
|
-
* `limit` Sets the maximum size of the `string/text/binary/integer` fields
|
301
|
-
* `precision` Defines the precision for the `decimal` fields
|
302
|
-
* `scale` Defines the scale for the `decimal` fields
|
303
|
-
* `polymorphic` Adds a `type` column for `belongs_to` associations
|
300
|
+
* `limit` Sets the maximum size of the `string/text/binary/integer` fields.
|
301
|
+
* `precision` Defines the precision for the `decimal` fields, representing the total number of digits in the number.
|
302
|
+
* `scale` Defines the scale for the `decimal` fields, representing the number of digits after the decimal point.
|
303
|
+
* `polymorphic` Adds a `type` column for `belongs_to` associations.
|
304
304
|
* `null` Allows or disallows `NULL` values in the column.
|
305
305
|
|
306
306
|
For instance, running:
|
@@ -642,7 +642,7 @@ method for all the migrations that have not yet been run. If there are
|
|
642
642
|
no such migrations, it exits. It will run these migrations in order based
|
643
643
|
on the date of the migration.
|
644
644
|
|
645
|
-
Note that running the `db:migrate` also invokes the `db:schema:dump` task, which
|
645
|
+
Note that running the `db:migrate` task also invokes the `db:schema:dump` task, which
|
646
646
|
will update your `db/schema.rb` file to match the structure of your database.
|
647
647
|
|
648
648
|
If you specify a target version, Active Record will run the required migrations
|
data/guides/source/plugins.md
CHANGED
data/guides/source/routing.md
CHANGED
@@ -138,7 +138,7 @@ Sometimes, you have a resource that clients always look up without referencing a
|
|
138
138
|
get 'profile', to: 'users#show'
|
139
139
|
```
|
140
140
|
|
141
|
-
Passing a `String` to `
|
141
|
+
Passing a `String` to `get` will expect a `controller#action` format, while passing a `Symbol` will map directly to an action:
|
142
142
|
|
143
143
|
```ruby
|
144
144
|
get 'profile', to: :show
|
@@ -239,6 +239,8 @@ In each of these cases, the named routes remain the same as if you did not use `
|
|
239
239
|
| PATCH/PUT | /admin/posts/:id | posts#update | post_path(:id) |
|
240
240
|
| DELETE | /admin/posts/:id | posts#destroy | post_path(:id) |
|
241
241
|
|
242
|
+
TIP: _If you need to use a different controller namespace inside a `namespace` block you can specify an absolute controller path, e.g: `get '/foo' => '/foo#index'`._
|
243
|
+
|
242
244
|
### Nested Resources
|
243
245
|
|
244
246
|
It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
|
@@ -629,7 +631,7 @@ This will define a `user_path` method that will be available in controllers, hel
|
|
629
631
|
|
630
632
|
### HTTP Verb Constraints
|
631
633
|
|
632
|
-
In general, you should use the `get`, `post`, `put`
|
634
|
+
In general, you should use the `get`, `post`, `put`, `patch` and `delete` methods to constrain a route to a particular verb. You can use the `match` method with the `:via` option to match multiple verbs at once:
|
633
635
|
|
634
636
|
```ruby
|
635
637
|
match 'photos', to: 'photos#show', via: [:get, :post]
|
data/guides/source/security.md
CHANGED
@@ -81,7 +81,7 @@ Here are some general guidelines on sessions.
|
|
81
81
|
* _Do not store large objects in a session_. Instead you should store them in the database and save their id in the session. This will eliminate synchronization headaches and it won't fill up your session storage space (depending on what session storage you chose, see below).
|
82
82
|
This will also be a good idea, if you modify the structure of an object and old versions of it are still in some user's cookies. With server-side session storages you can clear out the sessions, but with client-side storages, this is hard to mitigate.
|
83
83
|
|
84
|
-
* _Critical data should not be stored in session_. If the user clears
|
84
|
+
* _Critical data should not be stored in session_. If the user clears their cookies or closes the browser, they will be lost. And with a client-side session storage, the user can read the data.
|
85
85
|
|
86
86
|
### Session Storage
|
87
87
|
|
@@ -150,7 +150,7 @@ Another countermeasure is to _save user-specific properties in the session_, ver
|
|
150
150
|
|
151
151
|
### Session Expiry
|
152
152
|
|
153
|
-
NOTE: _Sessions that never expire extend the time-frame for attacks such as cross-site
|
153
|
+
NOTE: _Sessions that never expire extend the time-frame for attacks such as cross-site request forgery (CSRF), session hijacking and session fixation._
|
154
154
|
|
155
155
|
One possibility is to set the expiry time-stamp of the cookie with the session id. However the client can edit cookies that are stored in the web browser so expiring sessions on the server is safer. Here is an example of how to _expire sessions in a database table_. Call `Session.sweep("20 minutes")` to expire sessions that were used longer than 20 minutes ago.
|
156
156
|
|
@@ -354,7 +354,7 @@ Having one single place in the admin interface or Intranet, where the input has
|
|
354
354
|
|
355
355
|
Refer to the Injection section for countermeasures against XSS. It is _recommended to use the SafeErb plugin_ also in an Intranet or administration interface.
|
356
356
|
|
357
|
-
**CSRF** Cross-Site
|
357
|
+
**CSRF** Cross-Site Request Forgery (CSRF), also known as Cross-Site Reference Forgery (XSRF), is a gigantic attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface.
|
358
358
|
|
359
359
|
A real-world example is a [router reconfiguration by CSRF](http://www.h-online.com/security/Symantec-reports-first-active-attack-on-a-DSL-router--/news/102352). The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had their credentials stolen.
|
360
360
|
|
@@ -549,7 +549,7 @@ Injection is very tricky, because the same code or parameter can be malicious in
|
|
549
549
|
|
550
550
|
### Whitelists versus Blacklists
|
551
551
|
|
552
|
-
NOTE: _When sanitizing, protecting or verifying something, whitelists over blacklists._
|
552
|
+
NOTE: _When sanitizing, protecting or verifying something, prefer whitelists over blacklists._
|
553
553
|
|
554
554
|
A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTML tags. This is opposed to a whitelist which lists the good e-mail addresses, public actions, good HTML tags and so on. Although sometimes it is not possible to create a whitelist (in a SPAM filter, for example), _prefer to use whitelist approaches_:
|
555
555
|
|
@@ -915,6 +915,49 @@ Content-Type: text/html
|
|
915
915
|
|
916
916
|
Under certain circumstances this would present the malicious HTML to the victim. However, this only seems to work with Keep-Alive connections (and many browsers are using one-time connections). But you can't rely on this. _In any case this is a serious bug, and you should update your Rails to version 2.0.5 or 2.1.2 to eliminate Header Injection (and thus response splitting) risks._
|
917
917
|
|
918
|
+
Unsafe Query Generation
|
919
|
+
-----------------------
|
920
|
+
|
921
|
+
Due to the way Active Record interprets parameters in combination with the way
|
922
|
+
that Rack parses query parameters it was possible to issue unexpected database
|
923
|
+
queries with `IS NULL` where clauses. As a response to that security issue
|
924
|
+
([CVE-2012-2660](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/8SA-M3as7A8/Mr9fi9X4kNgJ),
|
925
|
+
[CVE-2012-2694](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/jILZ34tAHF4/7x0hLH-o0-IJ)
|
926
|
+
and [CVE-2013-0155](https://groups.google.com/forum/#!searchin/rubyonrails-security/CVE-2012-2660/rubyonrails-security/c7jT-EeN9eI/L0u4e87zYGMJ))
|
927
|
+
`deep_munge` method was introduced as a solution to keep Rails secure by default.
|
928
|
+
|
929
|
+
Example of vulnerable code that could be used by attacker, if `deep_munge`
|
930
|
+
wasn't performed is:
|
931
|
+
|
932
|
+
```ruby
|
933
|
+
unless params[:token].nil?
|
934
|
+
user = User.find_by_token(params[:token])
|
935
|
+
user.reset_password!
|
936
|
+
end
|
937
|
+
```
|
938
|
+
|
939
|
+
When `params[:token]` is one of: `[]`, `[nil]`, `[nil, nil, ...]` or
|
940
|
+
`['foo', nil]` it will bypass the test for `nil`, but `IS NULL` or
|
941
|
+
`IN ('foo', NULL)` where clauses still will be added to the SQL query.
|
942
|
+
|
943
|
+
To keep rails secure by default, `deep_munge` replaces some of the values with
|
944
|
+
`nil`. Below table shows what the parameters look like based on `JSON` sent in
|
945
|
+
request:
|
946
|
+
|
947
|
+
| JSON | Parameters |
|
948
|
+
|-----------------------------------|--------------------------|
|
949
|
+
| `{ "person": null }` | `{ :person => nil }` |
|
950
|
+
| `{ "person": [] }` | `{ :person => nil }` |
|
951
|
+
| `{ "person": [null] }` | `{ :person => nil }` |
|
952
|
+
| `{ "person": [null, null, ...] }` | `{ :person => nil }` |
|
953
|
+
| `{ "person": ["foo", null] }` | `{ :person => ["foo"] }` |
|
954
|
+
|
955
|
+
It is possible to return to old behaviour and disable `deep_munge` configuring
|
956
|
+
your application if you are aware of the risk and know how to handle it:
|
957
|
+
|
958
|
+
```ruby
|
959
|
+
config.action_dispatch.perform_deep_munge = false
|
960
|
+
```
|
918
961
|
|
919
962
|
Default Headers
|
920
963
|
---------------
|
data/guides/source/testing.md
CHANGED
@@ -211,31 +211,9 @@ This line of code is called an _assertion_. An assertion is a line of code that
|
|
211
211
|
|
212
212
|
Every test contains one or more assertions. Only when all the assertions are successful will the test pass.
|
213
213
|
|
214
|
-
###
|
214
|
+
### Maintaining the test database schema
|
215
215
|
|
216
|
-
|
217
|
-
|
218
|
-
```bash
|
219
|
-
$ rake db:migrate
|
220
|
-
...
|
221
|
-
$ rake db:test:load
|
222
|
-
```
|
223
|
-
|
224
|
-
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.
|
225
|
-
|
226
|
-
NOTE: `db:test:prepare` will fail with an error if `db/schema.rb` doesn't exist.
|
227
|
-
|
228
|
-
#### Rake Tasks for Preparing your Application for Testing
|
229
|
-
|
230
|
-
| Tasks | Description |
|
231
|
-
| ------------------------------ | ------------------------------------------------------------------------- |
|
232
|
-
| `rake db:test:clone` | Recreate the test database from the current environment's database schema |
|
233
|
-
| `rake db:test:clone_structure` | Recreate the test database from the development structure |
|
234
|
-
| `rake db:test:load` | Recreate the test database from the current `schema.rb` |
|
235
|
-
| `rake db:test:prepare` | Check for pending migrations and load the test schema |
|
236
|
-
| `rake db:test:purge` | Empty the test database. |
|
237
|
-
|
238
|
-
TIP: You can see all these rake tasks and their descriptions by running `rake --tasks --describe`
|
216
|
+
In order to run your tests, your test database will need to have the current structure. The test helper checks whether your test database has any pending migrations. If so, it will try to load your `db/schema.rb` or `db/structure.sql` into the test database. If migrations are still pending, an error will be raised.
|
239
217
|
|
240
218
|
### Running Tests
|
241
219
|
|
@@ -361,7 +339,7 @@ NOTE: The execution of each test method stops as soon as any error or an asserti
|
|
361
339
|
|
362
340
|
When a test fails you are presented with the corresponding backtrace. By default
|
363
341
|
Rails filters that backtrace and will only print lines relevant to your
|
364
|
-
application. This eliminates the
|
342
|
+
application. This eliminates the framework noise and helps to focus on your
|
365
343
|
code. However there are situations when you want to see the full
|
366
344
|
backtrace. simply set the `BACKTRACE` environment variable to enable this
|
367
345
|
behavior:
|
@@ -423,8 +401,8 @@ Rails adds some custom assertions of its own to the `test/unit` framework:
|
|
423
401
|
| `assert_no_difference(expressions, message = nil, &block)` | Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
|
424
402
|
| `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.|
|
425
403
|
| `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.|
|
426
|
-
| `assert_response(type, message = nil)` | Asserts that the response comes with a specific status code. You can specify `:success` to indicate 200-299, `:redirect` to indicate 300-399, `:missing` to indicate 404, or `:error` to match the 500-599 range
|
427
|
-
| `assert_redirected_to(options = {}, message=nil)` | Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that `assert_redirected_to(controller: "weblog")` will also match the redirection of `redirect_to(controller: "weblog", action: "show")` and so on
|
404
|
+
| `assert_response(type, message = nil)` | Asserts that the response comes with a specific status code. You can specify `:success` to indicate 200-299, `:redirect` to indicate 300-399, `:missing` to indicate 404, or `:error` to match the 500-599 range. You can also pass an explicit status number or its symbolic equivalent. For more information, see [full list of status codes](http://rubydoc.info/github/rack/rack/master/Rack/Utils#HTTP_STATUS_CODES-constant) and how their [mapping](http://rubydoc.info/github/rack/rack/master/Rack/Utils#SYMBOL_TO_STATUS_CODE-constant) works.|
|
405
|
+
| `assert_redirected_to(options = {}, message=nil)` | Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that `assert_redirected_to(controller: "weblog")` will also match the redirection of `redirect_to(controller: "weblog", action: "show")` and so on. You can also pass named routes such as `assert_redirected_to root_path` and Active Record objects such as `assert_redirected_to @article`.|
|
428
406
|
| `assert_template(expected = nil, message=nil)` | Asserts that the request was rendered with the appropriate template file.|
|
429
407
|
|
430
408
|
You'll see the usage of some of these assertions in the next chapter.
|
@@ -540,8 +518,10 @@ You also have access to three instance variables in your functional tests:
|
|
540
518
|
|
541
519
|
### Setting Headers and CGI variables
|
542
520
|
|
543
|
-
|
544
|
-
|
521
|
+
[HTTP headers](http://tools.ietf.org/search/rfc2616#section-5.3)
|
522
|
+
and
|
523
|
+
[CGI variables](http://tools.ietf.org/search/rfc3875#section-4.1)
|
524
|
+
can be set directly on the `@request` instance variable:
|
545
525
|
|
546
526
|
```ruby
|
547
527
|
# setting a HTTP Header
|
@@ -784,7 +764,7 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
|
|
784
764
|
u = users(user)
|
785
765
|
sess.https!
|
786
766
|
sess.post "/login", username: u.username, password: u.password
|
787
|
-
assert_equal '/welcome', path
|
767
|
+
assert_equal '/welcome', sess.path
|
788
768
|
sess.https!(false)
|
789
769
|
end
|
790
770
|
end
|
@@ -959,7 +939,6 @@ Here's a unit test to test a mailer named `UserMailer` whose action `invite` is
|
|
959
939
|
require 'test_helper'
|
960
940
|
|
961
941
|
class UserMailerTest < ActionMailer::TestCase
|
962
|
-
tests UserMailer
|
963
942
|
test "invite" do
|
964
943
|
# Send the email, then test that it got queued
|
965
944
|
email = UserMailer.create_invite('me@example.com',
|
@@ -62,7 +62,7 @@ If you want to use Spring as your application preloader you need to:
|
|
62
62
|
|
63
63
|
NOTE: User defined rake tasks will run in the `development` environment by
|
64
64
|
default. If you want them to run in other environments consult the
|
65
|
-
[Spring README](https://github.com/
|
65
|
+
[Spring README](https://github.com/rails/spring#rake).
|
66
66
|
|
67
67
|
### `config/secrets.yml`
|
68
68
|
|
@@ -91,6 +91,26 @@ secrets, you need to:
|
|
91
91
|
|
92
92
|
5. Restart your server.
|
93
93
|
|
94
|
+
### Changes to test helper
|
95
|
+
|
96
|
+
If your test helper contains a call to
|
97
|
+
`ActiveRecord::Migration.check_pending!` this can be removed. The check
|
98
|
+
is now done automatically when you `require 'test_help'`, although
|
99
|
+
leaving this line in your helper is not harmful in any way.
|
100
|
+
|
101
|
+
### Cookies serializer
|
102
|
+
|
103
|
+
Applications created before Rails 4.1 uses `Marshal` to serialize cookie values into
|
104
|
+
the signed and encrypted cookie jars. If you want to use the new `JSON`-based format
|
105
|
+
in your application, you can add an initializer file with the following content:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
Rails.application.config.cookies_serializer :hybrid
|
109
|
+
```
|
110
|
+
|
111
|
+
This would transparently migrate your existing `Marshal`-serialized cookies into the
|
112
|
+
new `JSON`-based format.
|
113
|
+
|
94
114
|
### Changes in JSON handling
|
95
115
|
|
96
116
|
There are a few major changes related to JSON handling in Rails 4.1.
|
@@ -123,7 +143,7 @@ Rails-specific features. For example:
|
|
123
143
|
```ruby
|
124
144
|
class FooBar
|
125
145
|
def as_json(options = nil)
|
126
|
-
{ foo:
|
146
|
+
{ foo: 'bar' }
|
127
147
|
end
|
128
148
|
end
|
129
149
|
|
@@ -141,7 +161,7 @@ part of the rewrite, the following features have been removed from the encoder:
|
|
141
161
|
2. Support for the `encode_json` hook
|
142
162
|
3. Option to encode `BigDecimal` objects as numbers instead of strings
|
143
163
|
|
144
|
-
If
|
164
|
+
If your application depends on one of these features, you can get them back by
|
145
165
|
adding the [`activesupport-json_encoder`](https://github.com/rails/activesupport-json_encoder)
|
146
166
|
gem to your Gemfile.
|
147
167
|
|
@@ -242,6 +262,92 @@ authors = Author.where(name: 'Hank Moody').to_a
|
|
242
262
|
authors.compact!
|
243
263
|
```
|
244
264
|
|
265
|
+
### Changes on Default Scopes
|
266
|
+
|
267
|
+
Default scopes are no longer overriden by chained conditions.
|
268
|
+
|
269
|
+
In previous versions when you defined a `default_scope` in a model
|
270
|
+
it was overriden by chained conditions in the same field. Now it
|
271
|
+
is merged like any other scope.
|
272
|
+
|
273
|
+
Before:
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
class User < ActiveRecord::Base
|
277
|
+
default_scope { where state: 'pending' }
|
278
|
+
scope :active, -> { where state: 'active' }
|
279
|
+
scope :inactive, -> { where state: 'inactive' }
|
280
|
+
end
|
281
|
+
|
282
|
+
User.all
|
283
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
|
284
|
+
|
285
|
+
User.active
|
286
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
|
287
|
+
|
288
|
+
User.where(state: 'inactive')
|
289
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
|
290
|
+
```
|
291
|
+
|
292
|
+
After:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
class User < ActiveRecord::Base
|
296
|
+
default_scope { where state: 'pending' }
|
297
|
+
scope :active, -> { where state: 'active' }
|
298
|
+
scope :inactive, -> { where state: 'inactive' }
|
299
|
+
end
|
300
|
+
|
301
|
+
User.all
|
302
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
|
303
|
+
|
304
|
+
User.active
|
305
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'active'
|
306
|
+
|
307
|
+
User.where(state: 'inactive')
|
308
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'inactive'
|
309
|
+
```
|
310
|
+
|
311
|
+
To get the previous behavior it is needed to explicitly remove the
|
312
|
+
`default_scope` condition using `unscoped`, `unscope`, `rewhere` or
|
313
|
+
`except`.
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
class User < ActiveRecord::Base
|
317
|
+
default_scope { where state: 'pending' }
|
318
|
+
scope :active, -> { unescope(where: :state).where(state: 'active') }
|
319
|
+
scope :inactive, -> { rewhere state: 'inactive' }
|
320
|
+
end
|
321
|
+
|
322
|
+
User.all
|
323
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
|
324
|
+
|
325
|
+
User.active
|
326
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
|
327
|
+
|
328
|
+
User.inactive
|
329
|
+
# SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
|
330
|
+
```
|
331
|
+
|
332
|
+
### Rendering content from string
|
333
|
+
|
334
|
+
Rails 4.1 introduces `:plain`, `:html`, and `:body` options to `render`. Those
|
335
|
+
options are now the preferred way to render string-based content, as it allows
|
336
|
+
you to specify which content type you want the response sent as.
|
337
|
+
|
338
|
+
* `render :plain` will set the content type to `text/plain`
|
339
|
+
* `render :html` will set the content type to `text/html`
|
340
|
+
* `render :body` will *not* set the content type header.
|
341
|
+
|
342
|
+
From the security standpoint, if you don't expect to have any markup in your
|
343
|
+
response body, you should be using `render :plain` as most browsers will escape
|
344
|
+
unsafe content in the response for you.
|
345
|
+
|
346
|
+
We will be deprecating the use of `render :text` in a future version. So please
|
347
|
+
start using the more precise `:plain:`, `:html`, and `:body` options instead.
|
348
|
+
Using `render :text` may pose a security risk, as the content is sent as
|
349
|
+
`text/html`.
|
350
|
+
|
245
351
|
Upgrading from Rails 3.2 to Rails 4.0
|
246
352
|
-------------------------------------
|
247
353
|
|
@@ -313,7 +419,7 @@ being used, you can update your form to use the `PUT` method instead:
|
|
313
419
|
<%= form_for [ :update_name, @user ], method: :put do |f| %>
|
314
420
|
```
|
315
421
|
|
316
|
-
For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/
|
422
|
+
For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
|
317
423
|
on the Rails blog.
|
318
424
|
|
319
425
|
#### A note about media types
|
@@ -496,13 +602,13 @@ get 'こんにちは', controller: 'welcome', action: 'index'
|
|
496
602
|
|
497
603
|
```ruby
|
498
604
|
# Rails 3.x
|
499
|
-
match
|
605
|
+
match '/' => 'root#index'
|
500
606
|
|
501
607
|
# becomes
|
502
|
-
match
|
608
|
+
match '/' => 'root#index', via: :get
|
503
609
|
|
504
610
|
# or
|
505
|
-
get
|
611
|
+
get '/' => 'root#index'
|
506
612
|
```
|
507
613
|
|
508
614
|
* Rails 4.0 has removed `ActionDispatch::BestStandardsSupport` middleware, `<!DOCTYPE html>` already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`.
|
@@ -547,9 +653,8 @@ Active Record Observer and Action Controller Sweeper have been extracted to the
|
|
547
653
|
|
548
654
|
### sprockets-rails
|
549
655
|
|
550
|
-
* `assets:precompile:primary`
|
551
|
-
* The `config.assets.compress` option should be changed to
|
552
|
-
`config.assets.js_compressor` like so for instance:
|
656
|
+
* `assets:precompile:primary` and `assets:precompile:all` have been removed. Use `assets:precompile` instead.
|
657
|
+
* The `config.assets.compress` option should be changed to `config.assets.js_compressor` like so for instance:
|
553
658
|
|
554
659
|
```ruby
|
555
660
|
config.assets.js_compressor = :uglifier
|
@@ -557,7 +662,7 @@ config.assets.js_compressor = :uglifier
|
|
557
662
|
|
558
663
|
### sass-rails
|
559
664
|
|
560
|
-
* `asset-url` with two arguments is deprecated. For example: `asset-url("rails.png", image)` becomes `asset-url("rails.png")
|
665
|
+
* `asset-url` with two arguments is deprecated. For example: `asset-url("rails.png", image)` becomes `asset-url("rails.png")`.
|
561
666
|
|
562
667
|
Upgrading from Rails 3.1 to Rails 3.2
|
563
668
|
-------------------------------------
|
@@ -607,6 +712,10 @@ config.active_record.mass_assignment_sanitizer = :strict
|
|
607
712
|
|
608
713
|
Rails 3.2 deprecates `vendor/plugins` and Rails 4.0 will remove them completely. While it's not strictly necessary as part of a Rails 3.2 upgrade, you can start replacing any plugins by extracting them to gems and adding them to your Gemfile. If you choose not to make them gems, you can move them into, say, `lib/my_plugin/*` and add an appropriate initializer in `config/initializers/my_plugin.rb`.
|
609
714
|
|
715
|
+
### Active Record
|
716
|
+
|
717
|
+
Option `:dependent => :restrict` has been removed from `belongs_to`. If you want to prevent deleting the object if there are any associated objects, you can set `:dependent => :destroy` and return `false` after checking for existence of association from any of the associated object's destroy callbacks.
|
718
|
+
|
610
719
|
Upgrading from Rails 3.0 to Rails 3.1
|
611
720
|
-------------------------------------
|
612
721
|
|
@@ -694,7 +803,7 @@ You can help test performance with these additions to your test environment:
|
|
694
803
|
```ruby
|
695
804
|
# Configure static asset server for tests with Cache-Control for performance
|
696
805
|
config.serve_static_assets = true
|
697
|
-
config.static_cache_control =
|
806
|
+
config.static_cache_control = 'public, max-age=3600'
|
698
807
|
```
|
699
808
|
|
700
809
|
### config/initializers/wrap_parameters.rb
|