aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
Diffstat (limited to 'guides')
-rw-r--r--guides/CHANGELOG.md4
-rw-r--r--guides/Rakefile19
-rw-r--r--guides/bug_report_templates/action_controller_master.rb1
-rw-r--r--guides/bug_report_templates/active_job_master.rb1
-rw-r--r--guides/bug_report_templates/active_record_master.rb1
-rw-r--r--guides/bug_report_templates/active_record_migrations_master.rb1
-rw-r--r--guides/bug_report_templates/benchmark.rb1
-rw-r--r--guides/bug_report_templates/generic_master.rb1
-rw-r--r--guides/source/5_0_release_notes.md2
-rw-r--r--guides/source/action_controller_overview.md2
-rw-r--r--guides/source/active_model_basics.md53
-rw-r--r--guides/source/active_record_querying.md4
-rw-r--r--guides/source/asset_pipeline.md4
-rw-r--r--guides/source/association_basics.md22
-rw-r--r--guides/source/configuring.md12
-rw-r--r--guides/source/development_dependencies_install.md2
-rw-r--r--guides/source/form_helpers.md2
-rw-r--r--guides/source/getting_started.md8
-rw-r--r--guides/source/i18n.md10
-rw-r--r--guides/source/security.md4
-rw-r--r--guides/source/testing.md200
-rw-r--r--guides/source/upgrading_ruby_on_rails.md19
-rw-r--r--guides/w3c_validator.rb9
23 files changed, 314 insertions, 68 deletions
diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md
index 2730d2dfea..3a602efb3d 100644
--- a/guides/CHANGELOG.md
+++ b/guides/CHANGELOG.md
@@ -1,2 +1,6 @@
+## Rails 5.1.0.beta1 (February 23, 2017) ##
+
+* No changes.
+
Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/guides/CHANGELOG.md) for previous changes.
diff --git a/guides/Rakefile b/guides/Rakefile
index ccb42f3273..0a591558e1 100644
--- a/guides/Rakefile
+++ b/guides/Rakefile
@@ -2,15 +2,28 @@ namespace :guides do
desc 'Generate guides (for authors), use ONLY=foo to process just "foo.md"'
task generate: "generate:html"
+ # Guides are written in UTF-8, but the environment may be configured for some
+ # other locale, these tasks are responsible for ensuring the default external
+ # encoding is UTF-8.
+ #
+ # Real use cases: Generation was reported to fail on a machine configured with
+ # GBK (Chinese). The docs server once got misconfigured somehow and had "C",
+ # which broke generation too.
+ task :encoding do
+ %w(LANG LANGUAGE LC_ALL).each do |env_var|
+ ENV[env_var] = "en_US.UTF-8"
+ end
+ end
+
namespace :generate do
desc "Generate HTML guides"
- task :html do
+ task :html => :encoding do
ENV["WARNINGS"] = "1" # authors can't disable this
ruby "rails_guides.rb"
end
desc "Generate .mobi file. The kindlegen executable must be in your PATH. You can get it for free from http://www.amazon.com/gp/feature.html?docId=1000765211"
- task :kindle do
+ task :kindle => :encoding do
require "kindlerb"
unless Kindlerb.kindlegen_available?
abort "Please run `setupkindlerb` to install kindlegen"
@@ -25,7 +38,7 @@ namespace :guides do
# Validate guides -------------------------------------------------------------------------
desc 'Validate guides, use ONLY=foo to process just "foo.html"'
- task :validate do
+ task :validate => :encoding do
ruby "w3c_validator.rb"
end
diff --git a/guides/bug_report_templates/action_controller_master.rb b/guides/bug_report_templates/action_controller_master.rb
index 7644f6fe4a..486c7243ad 100644
--- a/guides/bug_report_templates/action_controller_master.rb
+++ b/guides/bug_report_templates/action_controller_master.rb
@@ -8,7 +8,6 @@ end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
- gem "arel", github: "rails/arel"
end
require "action_controller/railtie"
diff --git a/guides/bug_report_templates/active_job_master.rb b/guides/bug_report_templates/active_job_master.rb
index 7591470440..f61518713f 100644
--- a/guides/bug_report_templates/active_job_master.rb
+++ b/guides/bug_report_templates/active_job_master.rb
@@ -8,7 +8,6 @@ end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
- gem "arel", github: "rails/arel"
end
require "active_job"
diff --git a/guides/bug_report_templates/active_record_master.rb b/guides/bug_report_templates/active_record_master.rb
index 8bbc1ef19e..7265a671b0 100644
--- a/guides/bug_report_templates/active_record_master.rb
+++ b/guides/bug_report_templates/active_record_master.rb
@@ -8,7 +8,6 @@ end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
- gem "arel", github: "rails/arel"
gem "sqlite3"
end
diff --git a/guides/bug_report_templates/active_record_migrations_master.rb b/guides/bug_report_templates/active_record_migrations_master.rb
index 84a4b71909..13a375d1ba 100644
--- a/guides/bug_report_templates/active_record_migrations_master.rb
+++ b/guides/bug_report_templates/active_record_migrations_master.rb
@@ -8,7 +8,6 @@ end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
- gem "arel", github: "rails/arel"
gem "sqlite3"
end
diff --git a/guides/bug_report_templates/benchmark.rb b/guides/bug_report_templates/benchmark.rb
index a0b541d012..54433b34dd 100644
--- a/guides/bug_report_templates/benchmark.rb
+++ b/guides/bug_report_templates/benchmark.rb
@@ -8,7 +8,6 @@ end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
- gem "arel", github: "rails/arel"
gem "benchmark-ips"
end
diff --git a/guides/bug_report_templates/generic_master.rb b/guides/bug_report_templates/generic_master.rb
index ed45726e92..d3a7ae4ac4 100644
--- a/guides/bug_report_templates/generic_master.rb
+++ b/guides/bug_report_templates/generic_master.rb
@@ -8,7 +8,6 @@ end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
- gem "arel", github: "rails/arel"
end
require "active_support"
diff --git a/guides/source/5_0_release_notes.md b/guides/source/5_0_release_notes.md
index e1b3b0a42e..5f4be07351 100644
--- a/guides/source/5_0_release_notes.md
+++ b/guides/source/5_0_release_notes.md
@@ -242,7 +242,7 @@ Please refer to the [Changelog][railties] for detailed changes.
[Pull Request](https://github.com/rails/rails/pull/22288))
* New applications are generated with the evented file system monitor enabled
- on Linux and Mac OS X. The feature can be opted out by passing
+ on Linux and macOS. The feature can be opted out by passing
`--skip-listen` to the generator.
([commit](https://github.com/rails/rails/commit/de6ad5665d2679944a9ee9407826ba88395a1003),
[commit](https://github.com/rails/rails/commit/94dbc48887bf39c241ee2ce1741ee680d773f202))
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index 40eb838d32..69c4a00c5f 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -61,7 +61,7 @@ end
The [Layouts & Rendering Guide](layouts_and_rendering.html) explains this in more detail.
-`ApplicationController` inherits from `ActionController::Base`, which defines a number of helpful methods. This guide will cover some of these, but if you're curious to see what's in there, you can see all of them in the API documentation or in the source itself.
+`ApplicationController` inherits from `ActionController::Base`, which defines a number of helpful methods. This guide will cover some of these, but if you're curious to see what's in there, you can see all of them in the [API documentation](http://api.rubyonrails.org/classes/ActionController.html) or in the source itself.
Only public methods are callable as actions. It is a best practice to lower the visibility of methods (with `private` or `protected`) which are not intended to be actions, like auxiliary methods or filters.
diff --git a/guides/source/active_model_basics.md b/guides/source/active_model_basics.md
index 732e553c62..e26805d22c 100644
--- a/guides/source/active_model_basics.md
+++ b/guides/source/active_model_basics.md
@@ -87,7 +87,7 @@ end
### Conversion
If a class defines `persisted?` and `id` methods, then you can include the
-`ActiveModel::Conversion` module in that class and call the Rails conversion
+`ActiveModel::Conversion` module in that class, and call the Rails conversion
methods on objects of that class.
```ruby
@@ -156,16 +156,17 @@ person.changed? # => false
person.first_name = "First Name"
person.first_name # => "First Name"
-# returns true if any of the attributes have unsaved changes, false otherwise.
+# returns true if any of the attributes have unsaved changes.
person.changed? # => true
# returns a list of attributes that have changed before saving.
person.changed # => ["first_name"]
-# returns a hash of the attributes that have changed with their original values.
+# returns a Hash of the attributes that have changed with their original values.
person.changed_attributes # => {"first_name"=>nil}
-# returns a hash of changes, with the attribute names as the keys, and the values will be an array of the old and new value for that field.
+# returns a Hash of changes, with the attribute names as the keys, and the
+# values as an array of the old and new values for that field.
person.changes # => {"first_name"=>[nil, "First Name"]}
```
@@ -179,7 +180,7 @@ person.first_name # => "First Name"
person.first_name_changed? # => true
```
-Track what was the previous value of the attribute.
+Track the previous value of the attribute.
```ruby
# attr_name_was accessor
@@ -187,7 +188,7 @@ person.first_name_was # => nil
```
Track both previous and current value of the changed attribute. Returns an array
-if changed, else returns nil.
+if changed, otherwise returns nil.
```ruby
# attr_name_change
@@ -197,7 +198,7 @@ person.last_name_change # => nil
### Validations
-The `ActiveModel::Validations` module adds the ability to validate class objects
+The `ActiveModel::Validations` module adds the ability to validate objects
like in Active Record.
```ruby
@@ -225,7 +226,7 @@ person.valid? # => raises ActiveModel::StrictValidationFa
### Naming
-`ActiveModel::Naming` adds a number of class methods which make the naming and routing
+`ActiveModel::Naming` adds a number of class methods which make naming and routing
easier to manage. The module defines the `model_name` class method which
will define a number of accessors using some `ActiveSupport::Inflector` methods.
@@ -248,7 +249,7 @@ Person.model_name.singular_route_key # => "person"
### Model
-`ActiveModel::Model` adds the ability to a class to work with Action Pack and
+`ActiveModel::Model` adds the ability for a class to work with Action Pack and
Action View right out of the box.
```ruby
@@ -293,7 +294,7 @@ objects.
### Serialization
`ActiveModel::Serialization` provides basic serialization for your object.
-You need to declare an attributes hash which contains the attributes you want to
+You need to declare an attributes Hash which contains the attributes you want to
serialize. Attributes must be strings, not symbols.
```ruby
@@ -308,7 +309,7 @@ class Person
end
```
-Now you can access a serialized hash of your object using the `serializable_hash`.
+Now you can access a serialized Hash of your object using the `serializable_hash` method.
```ruby
person = Person.new
@@ -319,13 +320,14 @@ person.serializable_hash # => {"name"=>"Bob"}
#### ActiveModel::Serializers
-Rails provides an `ActiveModel::Serializers::JSON` serializer.
-This module automatically include the `ActiveModel::Serialization`.
+Active Model also provides the `ActiveModel::Serializers::JSON` module
+for JSON serializing / deserializing. This module automatically includes the
+previously discussed `ActiveModel::Serialization` module.
##### ActiveModel::Serializers::JSON
-To use the `ActiveModel::Serializers::JSON` you only need to change from
-`ActiveModel::Serialization` to `ActiveModel::Serializers::JSON`.
+To use `ActiveModel::Serializers::JSON` you only need to change the
+module you are including from `ActiveModel::Serialization` to `ActiveModel::Serializers::JSON`.
```ruby
class Person
@@ -339,7 +341,8 @@ class Person
end
```
-With the `as_json` method you have a hash representing the model.
+The `as_json` method, similar to `serializable_hash`, provides a Hash representing
+the model.
```ruby
person = Person.new
@@ -348,8 +351,8 @@ person.name = "Bob"
person.as_json # => {"name"=>"Bob"}
```
-From a JSON string you define the attributes of the model.
-You need to have the `attributes=` method defined on your class:
+You can also define the attributes for a model from a JSON string.
+However, you need to define the `attributes=` method on your class:
```ruby
class Person
@@ -369,7 +372,7 @@ class Person
end
```
-Now it is possible to create an instance of person and set the attributes using `from_json`.
+Now it is possible to create an instance of `Person` and set attributes using `from_json`.
```ruby
json = { name: 'Bob' }.to_json
@@ -389,8 +392,8 @@ class Person
end
```
-With the `human_attribute_name` you can transform attribute names into a more
-human format. The human format is defined in your locale file.
+With the `human_attribute_name` method, you can transform attribute names into a
+more human-readable format. The human-readable format is defined in your locale file(s).
* config/locales/app.pt-BR.yml
@@ -411,7 +414,7 @@ Person.human_attribute_name('name') # => "Nome"
`ActiveModel::Lint::Tests` allows you to test whether an object is compliant with
the Active Model API.
-* app/models/person.rb
+* `app/models/person.rb`
```ruby
class Person
@@ -419,7 +422,7 @@ the Active Model API.
end
```
-* test/models/person_test.rb
+* `test/models/person_test.rb`
```ruby
require 'test_helper'
@@ -454,9 +457,9 @@ features out of the box.
### SecurePassword
`ActiveModel::SecurePassword` provides a way to securely store any
-password in an encrypted form. On including this module, a
+password in an encrypted form. When you include this module, a
`has_secure_password` class method is provided which defines
-an accessor named `password` with certain validations on it.
+a `password` accessor with certain validations on it.
#### Requirements
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 31220f9be2..31865ea375 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1547,7 +1547,7 @@ SELECT people.id, people.name, comments.text
FROM people
INNER JOIN comments
ON comments.person_id = people.id
-WHERE comments.created_at = '2015-01-01'
+WHERE comments.created_at > '2015-01-01'
```
### Retrieving specific data from multiple tables
@@ -1871,7 +1871,7 @@ Which will execute:
```sql
SELECT count(DISTINCT clients.id) AS count_all FROM clients
- LEFT OUTER JOIN orders ON orders.client_id = client.id WHERE
+ LEFT OUTER JOIN orders ON orders.client_id = clients.id WHERE
(clients.first_name = 'Ryan' AND orders.status = 'received')
```
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index 360de9a584..68dde4482f 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -207,7 +207,7 @@ default .coffee and .scss files will not be precompiled on their own. See
precompiling works.
NOTE: You must have an ExecJS supported runtime in order to use CoffeeScript.
-If you are using Mac OS X or Windows, you have a JavaScript runtime installed in
+If you are using macOS or Windows, you have a JavaScript runtime installed in
your operating system. Check [ExecJS](https://github.com/rails/execjs#readme) documentation to know all supported JavaScript runtimes.
You can also disable generation of controller specific asset files by adding the
@@ -1117,7 +1117,7 @@ config.assets.js_compressor = :uglifier
```
NOTE: You will need an [ExecJS](https://github.com/rails/execjs#readme)
-supported runtime in order to use `uglifier`. If you are using Mac OS X or
+supported runtime in order to use `uglifier`. If you are using macOS or
Windows you have a JavaScript runtime installed in your operating system.
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 6e68935f9b..5794bfa666 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -154,7 +154,7 @@ case, the column definition might look like this:
```ruby
create_table :accounts do |t|
- t.belongs_to :supplier, index: true, unique: true, foreign_key: true
+ t.belongs_to :supplier, index: { unique: true }, foreign_key: true
# ...
end
```
@@ -582,14 +582,30 @@ class CreateBooks < ActiveRecord::Migration[5.0]
t.string :book_number
t.integer :author_id
end
-
- add_index :books, :author_id
end
end
```
If you create an association some time after you build the underlying model, you need to remember to create an `add_column` migration to provide the necessary foreign key.
+It's a good practice to add an index on the foreign key to improve queries
+performance and a foreign key constraint to ensure referential data integrity:
+
+```ruby
+class CreateBooks < ActiveRecord::Migration[5.0]
+ def change
+ create_table :books do |t|
+ t.datetime :published_at
+ t.string :book_number
+ t.integer :author_id
+ end
+
+ add_index :books, :author_id
+ add_foreign_key :books, :authors
+ end
+end
+```
+
#### Creating Join Tables for `has_and_belongs_to_many` Associations
If you create a `has_and_belongs_to_many` association, you need to explicitly create the joining table. Unless the name of the join table is explicitly specified by using the `:join_table` option, Active Record creates the name by using the lexical book of the class names. So a join between author and book models will give the default join table name of "authors_books" because "a" outranks "b" in lexical ordering.
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 251b038ec9..a4f3882124 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -350,9 +350,9 @@ All these configuration options are delegated to the `I18n` library.
`config/environments/production.rb` which is generated by Rails. The
default value is `true` if this configuration is not set.
-* `config.active_record.dump_schemas` controls which database schemas will be dumped when calling db:structure:dump.
- The options are `:schema_search_path` (the default) which dumps any schemas listed in schema_search_path,
- `:all` which always dumps all schemas regardless of the schema_search_path,
+* `config.active_record.dump_schemas` controls which database schemas will be dumped when calling `db:structure:dump`.
+ The options are `:schema_search_path` (the default) which dumps any schemas listed in `schema_search_path`,
+ `:all` which always dumps all schemas regardless of the `schema_search_path`,
or a string of comma separated schemas.
* `config.active_record.belongs_to_required_by_default` is a boolean value and
@@ -362,10 +362,10 @@ All these configuration options are delegated to the `I18n` library.
* `config.active_record.warn_on_records_fetched_greater_than` allows setting a
warning threshold for query result size. If the number of records returned
by a query exceeds the threshold, a warning is logged. This can be used to
- identify queries which might be causing memory bloat.
+ identify queries which might be causing a memory bloat.
* `config.active_record.index_nested_attribute_errors` allows errors for nested
- has_many relationships to be displayed with an index as well as the error.
+ `has_many` relationships to be displayed with an index as well as the error.
Defaults to `false`.
* `config.active_record.use_schema_cache_dump` enables users to get schema cache information
@@ -1308,7 +1308,7 @@ end
Otherwise, in every request Rails walks the application tree to check if
anything has changed.
-On Linux and Mac OS X no additional gems are needed, but some are required
+On Linux and macOS no additional gems are needed, but some are required
[for *BSD](https://github.com/guard/listen#on-bsd) and
[for Windows](https://github.com/guard/listen#on-windows).
diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md
index 16c7e782bc..7ec038eb4d 100644
--- a/guides/source/development_dependencies_install.md
+++ b/guides/source/development_dependencies_install.md
@@ -46,7 +46,7 @@ $ cd rails
The test suite must pass with any submitted code. No matter whether you are writing a new patch, or evaluating someone else's, you need to be able to run the tests.
-Install first SQLite3 and its development files for the `sqlite3` gem. Mac OS X
+Install first SQLite3 and its development files for the `sqlite3` gem. On macOS
users are done with:
```bash
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index 8ad76ad01e..0508b0fb38 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -531,7 +531,7 @@ To leverage time zone support in Rails, you have to ask your users what time zon
<%= time_zone_select(:person, :time_zone) %>
```
-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.
+There is also `time_zone_options_for_select` helper for a more manual (therefore more customizable) way of doing this. Read the [API documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-time_zone_options_for_select) to learn about the possible arguments for these two methods.
Rails _used_ to have a `country_select` helper for choosing countries, but this has been extracted to the [country_select plugin](https://github.com/stefanpenner/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).
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 8a451ab793..57b8472462 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -86,7 +86,7 @@ your prompt will look something like `c:\source_code>`
### Installing Rails
-Open up a command line prompt. On Mac OS X open Terminal.app, on Windows choose
+Open up a command line prompt. On macOS open Terminal.app, on Windows choose
"Run" from your Start menu and type 'cmd.exe'. Any commands prefaced with a
dollar sign `$` should be run in the command line. Verify that you have a
current version of Ruby installed:
@@ -98,7 +98,7 @@ ruby 2.3.1p112
TIP: A number of tools exist to help you quickly install Ruby and Ruby
on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org),
-while Mac OS X users can use [Tokaido](https://github.com/tokaido/tokaidoapp).
+while macOS users can use [Tokaido](https://github.com/tokaido/tokaidoapp).
For more installation methods for most Operating Systems take a look at
[ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/).
@@ -206,7 +206,7 @@ folder directly to the Ruby interpreter e.g. `ruby bin\rails server`.
TIP: Compiling CoffeeScript and JavaScript asset compression requires you
have a JavaScript runtime available on your system, in the absence
of a runtime you will see an `execjs` error during asset compilation.
-Usually Mac OS X and Windows come with a JavaScript runtime installed.
+Usually macOS and Windows come with a JavaScript runtime installed.
Rails adds the `therubyracer` gem to the generated `Gemfile` in a
commented line for new apps and you can uncomment if you need it.
`therubyrhino` is the recommended runtime for JRuby users and is added by
@@ -221,7 +221,7 @@ your application in action, open a browser window and navigate to
TIP: To stop the web server, hit Ctrl+C in the terminal window where it's
running. To verify the server has stopped you should see your command prompt
-cursor again. For most UNIX-like systems including Mac OS X this will be a
+cursor again. For most UNIX-like systems including macOS this will be a
dollar sign `$`. In development mode, Rails does not generally require you to
restart the server; changes you make in files will be automatically picked up by
the server.
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index ed8cf8a344..6c8706bc13 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -707,6 +707,7 @@ The `:count` interpolation variable has a special role in that it both is interp
```ruby
I18n.backend.store_translations :en, inbox: {
+ zero: 'no messages', # optional
one: 'one message',
other: '%{count} messages'
}
@@ -715,15 +716,20 @@ I18n.translate :inbox, count: 2
I18n.translate :inbox, count: 1
# => 'one message'
+
+I18n.translate :inbox, count: 0
+# => 'no messages'
```
The algorithm for pluralizations in `:en` is as simple as:
```ruby
-entry[count == 1 ? 0 : 1]
+lookup_key = :zero if count == 0 && entry.has_key?(:zero)
+lookup_key ||= count == 1 ? :one : :other
+entry[lookup_key]
```
-I.e. the translation denoted as `:one` is regarded as singular, the other is used as plural (including the count being zero).
+The translation denoted as `:one` is regarded as singular, and the `:other` is used as plural. If the count is zero, and a `:zero` entry is present, then it will be used instead of `:other`.
If the lookup for the key does not return a Hash suitable for pluralization, an `I18n::InvalidPluralizationData` exception is raised.
diff --git a/guides/source/security.md b/guides/source/security.md
index a81a782cf2..a57c6ea247 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -615,7 +615,7 @@ The two dashes start a comment ignoring everything after it. So the query return
Usually a web application includes access control. The user enters their login credentials and 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.
```ruby
-User.first("login = '#{params[:name]}' AND password = '#{params[:password]}'")
+User.find_by("login = '#{params[:name]}' AND password = '#{params[:password]}'")
```
If an attacker enters ' OR '1'='1 as the name, and ' OR '2'>'1 as the password, the resulting SQL query will be:
@@ -762,7 +762,7 @@ s = sanitize(user_input, tags: tags, attributes: %w(href title))
This allows only the given tags and does a good job, even against all kinds of tricks and malformed tags.
-As a second step, _it is good practice to escape all output of the application_, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). _Use `escapeHTML()` (or its alias `h()`) method_ to replace the HTML input characters &amp;, &quot;, &lt;, and &gt; by their uninterpreted representations in HTML (`&amp;`, `&quot;`, `&lt;`, and `&gt;`).
+As a second step, _it is good practice to escape all output of the application_, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). _Use `escapeHTML()` (or its alias `h()`) method_ to replace the HTML input characters &amp;, &quot;, &lt;, and &gt; by their uninterpreted representations in HTML (`&amp;`, `&quot;`, `&lt;`, and `&gt;`).
##### Obfuscation and Encoding Injection
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 6f783089a9..27f5b5e916 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -8,7 +8,7 @@ This guide covers built-in mechanisms in Rails for testing your application.
After reading this guide, you will know:
* Rails testing terminology.
-* How to write unit, functional, and integration tests for your application.
+* How to write unit, functional, integration, and system tests for your application.
* Other popular testing approaches and plugins.
--------------------------------------------------------------------------------
@@ -33,18 +33,27 @@ Rails creates a `test` directory for you as soon as you create a Rails project u
```bash
$ ls -F test
-controllers/ helpers/ mailers/ test_helper.rb
-fixtures/ integration/ models/
+controllers/ helpers/ mailers/ system/ test_helper.rb
+fixtures/ integration/ models/ application_system_test_case.rb
```
The `helpers`, `mailers`, and `models` directories are meant to hold tests for view helpers, mailers, and models, respectively. The `controllers` directory is meant to hold tests for controllers, routes, and views. The `integration` directory is meant to hold tests for interactions between controllers.
+The system test directory holds system tests, which are used for full browser
+testing of your application. System tests allow you to test your application
+the way your users experience it and help you test your JavaScript as well.
+System tests inherit from Capybara and perform in browser tests for your
+application.
+
Fixtures are a way of organizing test data; they reside in the `fixtures` directory.
A `jobs` directory will also be created when an associated test is first generated.
The `test_helper.rb` file holds the default configuration for your tests.
+The `application_system_test_case.rb` holds the default configuration for your system
+tests.
+
### The Test Environment
@@ -114,7 +123,7 @@ def test_the_truth
end
```
-However only the `test` macro allows a more readable test name. You can still use regular method definitions though.
+Although you can still use regular method definitions, using the `test` macro allows for a more readable test name.
NOTE: The method name is generated by replacing spaces with underscores. The result does not need to be a valid Ruby identifier though, the name may contain punctuation characters etc. That's because in Ruby technically any string may be a method name. This may require use of `define_method` and `send` calls to function properly, but formally there's little restriction on the name.
@@ -358,6 +367,7 @@ All the basic assertions such as `assert_equal` defined in `Minitest::Assertions
* [`ActionView::TestCase`](http://api.rubyonrails.org/classes/ActionView/TestCase.html)
* [`ActionDispatch::IntegrationTest`](http://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html)
* [`ActiveJob::TestCase`](http://api.rubyonrails.org/classes/ActiveJob/TestCase.html)
+* [`ActionDispatch::SystemTestCase`](http://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html)
Each of these classes include `Minitest::Assertions`, allowing us to use all of the basic assertions in our tests.
@@ -587,6 +597,182 @@ create test/fixtures/articles.yml
Model tests don't have their own superclass like `ActionMailer::TestCase` instead they inherit from [`ActiveSupport::TestCase`](http://api.rubyonrails.org/classes/ActiveSupport/TestCase.html).
+System Testing
+--------------
+
+System tests are full-browser tests that can be used to test your application's
+JavaScript and user experience. System tests use Capybara as a base.
+
+System tests allow for running tests in either a real browser or a headless
+driver for testing full user interactions with your application.
+
+For creating Rails system tests, you use the `test/system` directory in your
+application. Rails provides a generator to create a system test skeleton for you.
+
+```bash
+$ bin/rails generate system_test users_create
+ invoke test_unit
+ create test/system/users_creates_test.rb
+```
+
+Here's what a freshly-generated system test looks like:
+
+```ruby
+require "application_system_test_case"
+
+class UsersCreatesTest < ApplicationSystemTestCase
+ # test "visiting the index" do
+ # visit users_creates_url
+ #
+ # assert_selector "h1", text: "UsersCreate"
+ # end
+end
+```
+
+By default, system tests are run with the Selenium driver, using the Chrome
+browser, and a screen size of 1400x1400. The next section explains how to
+change the default settings.
+
+### Changing the default settings
+
+Rails makes changing the default settings for system tests very simple. All
+the setup is abstracted away so you can focus on writing your tests.
+
+When you generate a new application or scaffold, an `application_system_test_case.rb` file
+is created in the test directory. This is where all the configuration for your
+system tests should live.
+
+If you want to change the default settings you can simply change what the system
+tests are "driven by". Say you want to change the driver from Selenium to
+Poltergeist. First add the Poltergeist gem to your Gemfile. Then in your
+`application_system_test_case.rb` file do the following:
+
+```ruby
+require "test_helper"
+require "capybara/poltergeist"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+ driven_by :poltergeist
+end
+```
+
+The driver name is a required argument for `driven_by`. The optional arguments
+that can be passed to `driven_by` are `:using` for the browser (this will only
+be used for non-headless drivers like Selenium), and `:screen_size` to change
+the size of the screen for screenshots.
+
+```ruby
+require "test_helper"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+ driven_by :selenium, using: :firefox
+end
+```
+
+If your Capybara configuration requires more setup than provided by Rails, all
+of that configuration can be put into the `application_system_test_case.rb` file.
+
+Please see [Capybara's documentation](https://github.com/teamcapybara/capybara#setup)
+for additional settings.
+
+### Screenshot Helper
+
+The `ScreenshotHelper` is a helper designed to capture screenshots of your tests.
+This can be helpful for viewing the browser at the point a test failed, or
+to view screenshots later for debugging.
+
+Two methods are provided: `take_screenshot` and `take_failed_screenshot`.
+`take_failed_screenshot` is automatically included in `after_teardown` inside
+Rails.
+
+The `take_screenshot` helper method can be included anywhere in your tests to
+take a screenshot of the browser.
+
+### Implementing a system test
+
+Now we're going to add a system test to our blog application. We'll demonstrate
+writing a system test by visiting the index page and creating a new blog article.
+
+If you used the scaffold generator, a system test skeleton is automatically
+created for you. If you did not use the generator start by creating a system
+test skeleton.
+
+```bash
+$ bin/rails generate system_test articles
+```
+
+It should have created a test file placeholder for us. With the output of the
+previous command you should see:
+
+```bash
+ invoke test_unit
+ create test/system/articles_test.rb
+```
+
+Now let's open that file and write our first assertion:
+
+```ruby
+require "application_system_test_case"
+
+class ArticlesTest < ApplicationSystemTestCase
+ test "viewing the index" do
+ visit articles_path
+ assert_selector "h1", text: "Articles"
+ end
+end
+```
+
+The test should see that there is an h1 on the articles index and pass.
+
+Run the system tests.
+
+```bash
+bin/rails test:system
+```
+
+NOTE: By default, running `bin/rails test` won't run your system tests.
+Make sure to run `bin/rails test:system` to actually run them.
+
+#### Creating articles system test
+
+Now let's test the flow for creating a new article in our blog.
+
+```ruby
+test "creating an article" do
+ visit articles_path
+
+ click_on "New Article"
+
+ fill_in "Title", with: "Creating an Article"
+ fill_in "Body", with: "Created this article successfully!"
+
+ click_on "Create Article"
+
+ assert_text "Creating an Article"
+end
+```
+
+The first step is to call `visit articles_path`. This will take the test to the
+articles index page.
+
+Then the `click_on "New Article"` will find the "New Article" button on the
+index page. This will redirect the browser to `/articles/new`.
+
+Then the test will fill in the title and body of the article with the specified
+text. Once the fields are filled in, "Create Article" is clicked on which will
+send a POST request to create the new article in the database.
+
+We will be redirected back to the the articles index page and there we assert
+that the text from the article title is on the articles index page.
+
+#### Taking it further
+
+The beauty of system testing is that it is similar to integration testing in
+that it tests the user's interaction with your controller, model, and view, but
+system testing is much more robust and actually tests your application as if
+a real user were using it. Going forward, you can test anything that the user
+themselves would do in your application such as commenting, deleting articles,
+publishing draft articles, etc.
Integration Testing
-------------------
@@ -868,7 +1054,7 @@ class ArticlesControllerTest < ActionDispatch::IntegrationTest
assert_equal "index", @controller.action_name
assert_equal "application/x-www-form-urlencoded", @request.media_type
- assert_match "Articles", @response.body
+ assert_match "Articles", @response.body
end
end
```
@@ -1254,6 +1440,10 @@ variable. We then ensure that it was sent (the first assert), then, in the
second batch of assertions, we ensure that the email does indeed contain what we
expect. The helper `read_fixture` is used to read in the content from this file.
+NOTE: `email.body.to_s` is present when there's only one (HTML or text) part present.
+If the mailer provides both, you can test your fixture against specific parts
+with `email.text_part.body.to_s` or `email.html_part.body.to_s`.
+
Here's the content of the `invite` fixture:
```
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 8ba00a2b10..3afc0e5309 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -65,6 +65,25 @@ Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh]
Don't forget to review the difference, to see if there were any unexpected changes.
+Upgrading from Rails 5.0 to Rails 5.1
+-------------------------------------
+
+For more information on changes made to Rails 5.1 please see the [release notes](5_1_release_notes.html).
+
+### Top-level `HashWithIndifferentAccess` is soft-deprecated
+
+If your application uses the the top-level `HashWithIndifferentAccess` class, you
+should slowly move your code to use the `ActiveSupport::HashWithIndifferentAccess`
+one.
+
+It is only soft-deprecated, which means that your code will not break at the
+moment and no deprecation warning will be displayed but this constant will be
+removed in the future.
+
+Also, if you have pretty old YAML documents containing dumps of such objects,
+you may need to load and dump them again to make sure that they reference
+the right constant and that loading them won't break in the future.
+
Upgrading from Rails 4.2 to Rails 5.0
-------------------------------------
diff --git a/guides/w3c_validator.rb b/guides/w3c_validator.rb
index c0a32c6b91..4671e040ca 100644
--- a/guides/w3c_validator.rb
+++ b/guides/w3c_validator.rb
@@ -32,7 +32,8 @@ include W3CValidators
module RailsGuides
class Validator
def validate
- validator = MarkupValidator.new
+ # https://github.com/w3c-validators/w3c_validators/issues/25
+ validator = NuValidator.new
STDOUT.sync = true
errors_on_guides = {}
@@ -44,11 +45,11 @@ module RailsGuides
next
end
- if results.validity
- print "."
- else
+ if results.errors.length > 0
print "E"
errors_on_guides[f] = results.errors
+ else
+ print "."
end
end