diff options
Diffstat (limited to 'guides/source')
-rw-r--r-- | guides/source/action_view_overview.md | 2 | ||||
-rw-r--r-- | guides/source/active_job_basics.md | 2 | ||||
-rw-r--r-- | guides/source/active_record_postgresql.md | 46 | ||||
-rw-r--r-- | guides/source/association_basics.md | 5 | ||||
-rw-r--r-- | guides/source/configuring.md | 6 | ||||
-rw-r--r-- | guides/source/contributing_to_ruby_on_rails.md | 4 | ||||
-rw-r--r-- | guides/source/form_helpers.md | 21 | ||||
-rw-r--r-- | guides/source/i18n.md | 2 | ||||
-rw-r--r-- | guides/source/layouts_and_rendering.md | 4 | ||||
-rw-r--r-- | guides/source/rails_on_rack.md | 10 | ||||
-rw-r--r-- | guides/source/routing.md | 2 | ||||
-rw-r--r-- | guides/source/security.md | 19 | ||||
-rw-r--r-- | guides/source/upgrading_ruby_on_rails.md | 25 |
13 files changed, 91 insertions, 57 deletions
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index 76454e77c7..4b0e9bff7c 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -1247,7 +1247,7 @@ file_field_tag 'attachment' #### form_tag -Starts a form tag that points the action to an url configured with `url_for_options` just like `ActionController::Base#url_for`. +Starts a form tag that points the action to a url configured with `url_for_options` just like `ActionController::Base#url_for`. ```html+erb <%= form_tag '/articles' do %> diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index e3502d7363..17087d187a 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -296,7 +296,7 @@ emails asynchronously: ```ruby I18n.locale = :eo -UserMailer.welcome(@user).deliver_later # Email will be localized to Esparanto. +UserMailer.welcome(@user).deliver_later # Email will be localized to Esperanto. ``` diff --git a/guides/source/active_record_postgresql.md b/guides/source/active_record_postgresql.md index 9d495dfacb..f71e6ccd57 100644 --- a/guides/source/active_record_postgresql.md +++ b/guides/source/active_record_postgresql.md @@ -220,11 +220,22 @@ normal text columns: ```ruby # db/migrate/20131220144913_create_articles.rb -execute <<-SQL - CREATE TYPE article_status AS ENUM ('draft', 'published'); -SQL -create_table :articles do |t| - t.column :status, :article_status +def up + execute <<-SQL + CREATE TYPE article_status AS ENUM ('draft', 'published'); + SQL + create_table :articles do |t| + t.column :status, :article_status + end +end + +# NOTE: It's important to drop table before dropping enum. +def down + drop_table :articles + + execute <<-SQL + DROP TYPE article_status; + SQL end # app/models/article.rb @@ -240,6 +251,31 @@ article.status = "published" article.save! ``` +To add a new value before/after existing one you should use [ALTER TYPE](http://www.postgresql.org/docs/current/static/sql-altertype.html): +```ruby +# db/migrate/20150720144913_add_new_state_to_articles.rb +# NOTE: ALTER TYPE ... ADD VALUE cannot be executed inside of a transaction block so here we are using disable_ddl_transaction! +disable_ddl_transaction! + +def up + execute <<-SQL + ALTER TYPE article_status ADD VALUE IF NOT EXISTS 'archived' AFTER 'published'; + SQL +end +``` + +NOTE: by now we can't drop ENUM values. You can read why [here](http://www.postgresql.org/message-id/29F36C7C98AB09499B1A209D48EAA615B7653DBC8A@mail2a.alliedtesting.com). + +Hint: to show all the values of the all enums you have, you should call this query in `bin/rails db` or `psql` console: +```sql +SELECT n.nspname AS enum_schema, + t.typname AS enum_name, + e.enumlabel AS enum_value + FROM pg_type t + JOIN pg_enum e ON t.oid = e.enumtypid + JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace +``` + ### UUID * [type definition](http://www.postgresql.org/docs/current/static/datatype-uuid.html) diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md index 60790b33a4..999c533fb3 100644 --- a/guides/source/association_basics.md +++ b/guides/source/association_basics.md @@ -932,8 +932,11 @@ If you set the `:dependent` option to: * `:destroy`, when the object is destroyed, `destroy` will be called on its associated objects. -* `:delete`, when the object is destroyed, all its associated objects will be +* `:delete_all`, when the object is destroyed, all its associated objects will be deleted directly from the database without calling their `destroy` method. +* `:nullify`, causes the foreign key to be set to `NULL`. Callbacks are not executed. +* `:restrict_with_exception`, causes an exception to be raised if there is an associated record +* `:restrict_with_error`, causes an error to be added to the owner if there is an associated object WARNING: You should not specify this option on a `belongs_to` association that is connected with a `has_many` association on the other class. Doing so can lead to orphaned records in your database. diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 0dd99cf8e9..87114c4ef0 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -244,7 +244,7 @@ config.middleware.swap ActionController::Failsafe, Lifo::Failsafe They can also be removed from the stack completely: ```ruby -config.middleware.delete "Rack::MethodOverride" +config.middleware.delete Rack::MethodOverride ``` ### Configuring i18n @@ -535,7 +535,7 @@ There are a few configuration options available in Active Support: * `config.active_support.time_precision` sets the precision of JSON encoded time values. Defaults to `3`. -* `config.active_support.halt_callback_chains_on_return_false` specifies whether ActiveRecord, ActiveModel and ActiveModel::Validations callback chains can be halted by returning `false` in a 'before' callback. Defaults to `true`. +* `ActiveSupport.halt_callback_chains_on_return_false` specifies whether Active Record and Active Model callback chains can be halted by returning `false` in a 'before' callback. Defaults to `true`. * `ActiveSupport::Logger.silencer` is set to `false` to disable the ability to silence logging in a block. The default is `true`. @@ -641,7 +641,7 @@ TIP: You don't have to update the database configurations manually. If you look ### Connection Preference -Since there are two ways to set your connection, via environment variable it is important to understand how the two can interact. +Since there are two ways to configure your connection (using `config/database.yml` or using an environment variable) it is important to understand how they can interact. If you have an empty `config/database.yml` file but your `ENV['DATABASE_URL']` is present, then Rails will connect to the database via your environment variable: diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index 625299c113..6d689804a8 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -128,7 +128,7 @@ Contributing to the Rails Documentation Ruby on Rails has two main sets of documentation: the guides, which help you learn about Ruby on Rails, and the API, which serves as a reference. -You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see [Translating Rails Guides](https://wiki.github.com/rails/docrails/translating-rails-guides). +You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing them up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see [Translating Rails Guides](https://wiki.github.com/rails/docrails/translating-rails-guides). You can either open a pull request to [Rails](http://github.com/rails/rails) or ask the [Rails core team](http://rubyonrails.org/core) for commit access on @@ -318,7 +318,7 @@ $ cd activerecord $ bundle exec rake test:sqlite3 ``` -You can now run the tests as you did for `sqlite3`. The tasks are respectively +You can now run the tests as you did for `sqlite3`. The tasks are respectively: ```bash test:mysql diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md index 84a8d695cb..0a6e2e5dba 100644 --- a/guides/source/form_helpers.md +++ b/guides/source/form_helpers.md @@ -40,7 +40,9 @@ When called without arguments like this, it creates a `<form>` tag which, when s </form> ``` -You'll notice that the HTML contains `input` element with type `hidden`. This `input` is important, because the form cannot be successfully submitted without it. The hidden input element has name attribute of `utf8` enforces browsers to properly respect your form's character encoding and is generated for all forms whether their actions are "GET" or "POST". The second input element with name `authenticity_token` is a security feature of Rails called **cross-site request forgery protection**, and form helpers generate it for every non-GET form (provided that this security feature is enabled). You can read more about this in the [Security Guide](security.html#cross-site-request-forgery-csrf). +You'll notice that the HTML contains an `input` element with type `hidden`. This `input` is important, because the form cannot be successfully submitted without it. The hidden input element with the name `utf8` enforces browsers to properly respect your form's character encoding and is generated for all forms whether their action is "GET" or "POST". + +The second input element with the name `authenticity_token` is a security feature of Rails called **cross-site request forgery protection**, and form helpers generate it for every non-GET form (provided that this security feature is enabled). You can read more about this in the [Security Guide](security.html#cross-site-request-forgery-csrf). ### A Generic Search Form @@ -103,9 +105,9 @@ checkboxes, text fields, and radio buttons. These basic helpers, with names ending in `_tag` (such as `text_field_tag` and `check_box_tag`), generate just a single `<input>` element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form -data, and will make its way to the `params` hash in the controller with the -value entered by the user for that field. For example, if the form contains `<%= -text_field_tag(:query) %>`, then you would be able to get the value of this +data, and will make its way to the `params` in the controller with the +value entered by the user for that field. For example, if the form contains +`<%= text_field_tag(:query) %>`, then you would be able to get the value of this field in the controller with `params[:query]`. When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in `params`. You can read more about them in [chapter 7 of this guide](#understanding-parameter-naming-conventions). For details on the precise usage of these helpers, please refer to the [API documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html). @@ -212,7 +214,7 @@ month, week, URL, email, number and range inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely [no shortage of solutions for this](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills), although a popular tool at the moment is -[Modernizr](http://www.modernizr.com/), which provides a simple way to add functionality based on the presence of +[Modernizr](https://modernizr.com/), which provides a simple way to add functionality based on the presence of detected HTML5 features. TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the [Security Guide](security.html#logging). @@ -376,7 +378,7 @@ output: </form> ``` -When parsing POSTed data, Rails will take into account the special `_method` parameter and acts as if the HTTP method was the one specified inside it ("PATCH" in this example). +When parsing POSTed data, Rails will take into account the special `_method` parameter and act as if the HTTP method was the one specified inside it ("PATCH" in this example). Making Select Boxes with Ease ----------------------------- @@ -711,13 +713,6 @@ action for a Person model, `params[:person]` would usually be a hash of all the Fundamentally HTML forms don't know about any sort of structured data, all they generate is name-value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses. -TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rack's parameter parser. For example, - -```ruby -Rack::Utils.parse_query "name=fred&phone=0123456789" -# => {"name"=>"fred", "phone"=>"0123456789"} -``` - ### Basic Structures The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in `params`. For example, if a form contains: diff --git a/guides/source/i18n.md b/guides/source/i18n.md index ea79855919..87d2fafaf3 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -249,7 +249,7 @@ end With this approach you will not get a `Routing Error` when accessing your resources such as `http://localhost:3001/books` without a locale. This is useful for when you want to use the default locale when one is not specified. -Of course, you need to take special care of the root URL (usually "homepage" or "dashboard") of your application. An URL like `http://localhost:3001/nl` will not work automatically, because the `root to: "books#index"` declaration in your `routes.rb` doesn't take locale into account. (And rightly so: there's only one "root" URL.) +Of course, you need to take special care of the root URL (usually "homepage" or "dashboard") of your application. A URL like `http://localhost:3001/nl` will not work automatically, because the `root to: "books#index"` declaration in your `routes.rb` doesn't take locale into account. (And rightly so: there's only one "root" URL.) You would probably need to map URLs like these: diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md index b425eb126a..71cc030f6a 100644 --- a/guides/source/layouts_and_rendering.md +++ b/guides/source/layouts_and_rendering.md @@ -280,7 +280,7 @@ render body: "raw" ``` TIP: This option should be used only if you don't care about the content type of -the response. Using `:plain` or `:html` might be more appropriate in most of the +the response. Using `:plain` or `:html` might be more appropriate most of the time. NOTE: Unless overridden, your response returned from this render option will be @@ -781,7 +781,7 @@ The `javascript_include_tag` helper returns an HTML `script` tag for each source If you are using Rails with the [Asset Pipeline](asset_pipeline.html) enabled, this helper will generate a link to `/assets/javascripts/` rather than `public/javascripts` which was used in earlier versions of Rails. This link is then served by the asset pipeline. -A JavaScript file within a Rails application or Rails engine goes in one of three locations: `app/assets`, `lib/assets` or `vendor/assets`. These locations are explained in detail in the [Asset Organization section in the Asset Pipeline Guide](asset_pipeline.html#asset-organization) +A JavaScript file within a Rails application or Rails engine goes in one of three locations: `app/assets`, `lib/assets` or `vendor/assets`. These locations are explained in detail in the [Asset Organization section in the Asset Pipeline Guide](asset_pipeline.html#asset-organization). You can specify a full path relative to the document root, or a URL, if you prefer. For example, to link to a JavaScript file that is inside a directory called `javascripts` inside of one of `app/assets`, `lib/assets` or `vendor/assets`, you would do this: diff --git a/guides/source/rails_on_rack.md b/guides/source/rails_on_rack.md index 0db90fedb3..87f869aff3 100644 --- a/guides/source/rails_on_rack.md +++ b/guides/source/rails_on_rack.md @@ -171,7 +171,7 @@ Add the following lines to your application configuration: ```ruby # config/application.rb -config.middleware.delete "Rack::Lock" +config.middleware.delete Rack::Lock ``` And now if you inspect the middleware stack, you'll find that `Rack::Lock` is @@ -191,16 +191,16 @@ If you want to remove session related middleware, do the following: ```ruby # config/application.rb -config.middleware.delete "ActionDispatch::Cookies" -config.middleware.delete "ActionDispatch::Session::CookieStore" -config.middleware.delete "ActionDispatch::Flash" +config.middleware.delete ActionDispatch::Cookies +config.middleware.delete ActionDispatch::Session::CookieStore +config.middleware.delete ActionDispatch::Flash ``` And to remove browser related middleware, ```ruby # config/application.rb -config.middleware.delete "Rack::MethodOverride" +config.middleware.delete Rack::MethodOverride ``` ### Internal Middleware Stack diff --git a/guides/source/routing.md b/guides/source/routing.md index 1fd38c0940..3175716a9c 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -1096,7 +1096,7 @@ Video.find_by(identifier: params[:identifier]) ``` You can override `ActiveRecord::Base#to_param` of a related model to construct -an URL: +a URL: ```ruby class Video < ActiveRecord::Base diff --git a/guides/source/security.md b/guides/source/security.md index 5a6ac9446a..fb9ee7b412 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -196,7 +196,7 @@ This attack method works by including malicious code or a link in a page that ac  -In the [session chapter](#sessions) you have learned that most Rails applications use cookie-based sessions. Either they store the session id in the cookie and have a server-side session hash, or the entire session hash is on the client-side. In either case the browser will automatically send along the cookie on every request to a domain, if it can find a cookie for that domain. The controversial point is, that it will also send the cookie, if the request comes from a site of a different domain. Let's start with an example: +In the [session chapter](#sessions) you have learned that most Rails applications use cookie-based sessions. Either they store the session id in the cookie and have a server-side session hash, or the entire session hash is on the client-side. In either case the browser will automatically send along the cookie on every request to a domain, if it can find a cookie for that domain. The controversial point is that if the request comes from a site of a different domain, it will also send the cookie. Let's start with an example: * Bob browses a message board and views a post from a hacker where there is a crafted HTML image element. The element references a command in Bob's project management application, rather than an image file: `<img src="http://www.webapp.com/project/1/destroy">` * Bob's session at `www.webapp.com` is still alive, because he didn't log out a few minutes ago. @@ -224,9 +224,9 @@ The HTTP protocol basically provides two main types of requests - GET and POST ( * The interaction _changes the state_ of the resource in a way that the user would perceive (e.g., a subscription to a service), or * The user is _held accountable for the results_ of the interaction. -If your web application is RESTful, you might be used to additional HTTP verbs, such as PATCH, 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. +If your web application is RESTful, you might be used to additional HTTP verbs, such as PATCH, 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. -_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. +_POST requests can be sent automatically, too_. In this example, the link www.harmless.com is shown as the destination in the browser's status bar. But it has actually dynamically created a new form that sends a POST request. ```html <a href="http://www.harmless.com/" onclick=" @@ -301,7 +301,7 @@ This will redirect the user to the main action if they tried to access a legacy http://www.example.com/site/legacy?param1=xy¶m2=23&host=www.attacker.com ``` -If it is at the end of the URL it will hardly be noticed and redirects the user to the attacker.com host. A simple countermeasure would be to _include only the expected parameters in a legacy action_ (again a whitelist approach, as opposed to removing unexpected parameters). _And if you redirect to an URL, check it with a whitelist or a regular expression_. +If it is at the end of the URL it will hardly be noticed and redirects the user to the attacker.com host. A simple countermeasure would be to _include only the expected parameters in a legacy action_ (again a whitelist approach, as opposed to removing unexpected parameters). _And if you redirect to a URL, check it with a whitelist or a regular expression_. #### Self-contained XSS @@ -406,7 +406,7 @@ NOTE: _Almost every web application has to deal with authorization and authentic There are a number of authentication plug-ins for Rails available. Good ones, such as the popular [devise](https://github.com/plataformatec/devise) and [authlogic](https://github.com/binarylogic/authlogic), store only encrypted passwords, not plain-text passwords. In Rails 3.1 you can use the built-in `has_secure_password` method which has similar features. -Every new user gets an activation code to activate their account when they get an e-mail with a link in it. After activating the account, the activation_code columns will be set to NULL in the database. If someone requested an URL like these, they would be logged in as the first activated user found in the database (and chances are that this is the administrator): +Every new user gets an activation code to activate their account when they get an e-mail with a link in it. After activating the account, the activation_code columns will be set to NULL in the database. If someone requested a URL like these, they would be logged in as the first activated user found in the database (and chances are that this is the administrator): ``` http://localhost:3006/user/activate @@ -793,15 +793,13 @@ Another proof-of-concept webmail worm is Nduja, a cross-domain worm for four Ita In December 2006, 34,000 actual user names and passwords were stolen in a [MySpace phishing attack](http://news.netcraft.com/archives/2006/10/27/myspace_accounts_compromised_by_phishers.html). The idea of the attack was to create a profile page named "login_home_index_html", so the URL looked very convincing. Specially-crafted HTML and CSS was used to hide the genuine MySpace content from the page and instead display its own login form. -The MySpace Samy worm will be discussed in the CSS Injection section. - ### CSS Injection INFO: _CSS Injection is actually JavaScript injection, because some browsers (IE, some versions of Safari and others) allow JavaScript in CSS. Think twice about allowing custom CSS in your web application._ -CSS Injection is explained best by a well-known worm, the [MySpace Samy worm](http://namb.la/popular/tech.html). This worm automatically sent a friend request to Samy (the attacker) simply by visiting his profile. Within several hours he had over 1 million friend requests, but it creates too much traffic on MySpace, so that the site goes offline. The following is a technical explanation of the worm. +CSS Injection is explained best by the well-known [MySpace Samy worm](http://namb.la/popular/tech.html). This worm automatically sent a friend request to Samy (the attacker) simply by visiting his profile. Within several hours he had over 1 million friend requests, which created so much traffic that MySpace went offline. The following is a technical explanation of that worm. -MySpace blocks many tags, however it allows CSS. So the worm's author put JavaScript into CSS like this: +MySpace blocked many tags, but allowed CSS. So the worm's author put JavaScript into CSS like this: ```html <div style="background:url('javascript:alert(1)')"> @@ -825,7 +823,7 @@ The next problem was MySpace filtering the word "javascript", so the author used <div id="mycode" expr="alert('hah!')" style="background:url('java↵
script:eval(document.all.mycode.expr)')"> ``` -Another problem for the worm's author were CSRF security tokens. Without them he couldn't send a friend request over POST. He got around it by sending a GET to the page right before adding a user and parsing the result for the CSRF token. +Another problem for the worm's author was the [CSRF security tokens](#cross-site-request-forgery-csrf). Without them he couldn't send a friend request over POST. He got around it by sending a GET to the page right before adding a user and parsing the result for the CSRF token. In the end, he got a 4 KB worm, which he injected into his profile page. @@ -1059,4 +1057,3 @@ The security landscape shifts and it is important to keep up to date, because mi * Subscribe to the Rails security [mailing list](http://groups.google.com/group/rubyonrails-security) * [Keep up to date on the other application layers](http://secunia.com/) (they have a weekly newsletter, too) * A [good security blog](https://www.owasp.org) including the [Cross-Site scripting Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet) - diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index 52464a1c51..490bda3571 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -55,23 +55,26 @@ Upgrading from Rails 4.2 to Rails 5.0 ### Halting callback chains by returning `false` -In Rails 4.2, when a 'before' callback returns `false` in ActiveRecord, -ActiveModel and ActiveModel::Validations, then the entire callback chain -is halted. In other words, successive 'before' callbacks are not executed, -and neither is the action wrapped in callbacks. +In Rails 4.2, when a 'before' callback returns `false` in Active Record +and Active Model, then the entire callback chain is halted. In other words, +successive 'before' callbacks are not executed, and neither is the action wrapped +in callbacks. -In Rails 5.0, returning `false` in a callback will not have this side effect -of halting the callback chain. Instead, callback chains must be explicitly -halted by calling `throw(:abort)`. +In Rails 5.0, returning `false` in an Active Record or Active Model callback +will not have this side effect of halting the callback chain. Instead, callback +chains must be explicitly halted by calling `throw(:abort)`. -When you upgrade from Rails 4.2 to Rails 5.0, returning `false` in a callback -will still halt the callback chain, but you will receive a deprecation warning -about this upcoming change. +When you upgrade from Rails 4.2 to Rails 5.0, returning `false` in those kind of +callbacks will still halt the callback chain, but you will receive a deprecation +warning about this upcoming change. When you are ready, you can opt into the new behavior and remove the deprecation warning by adding the following configuration to your `config/application.rb`: - config.active_support.halt_callback_chains_on_return_false = false + ActiveSupport.halt_callback_chains_on_return_false = false + +Note that this option will not affect Active Support callbacks since they never +halted the chain when any value was returned. See [#17227](https://github.com/rails/rails/pull/17227) for more details. |