aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md9
-rw-r--r--actionview/CHANGELOG.md6
-rw-r--r--activemodel/lib/active_model/validations/confirmation.rb2
-rw-r--r--activerecord/CHANGELOG.md5
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb6
-rw-r--r--activerecord/lib/active_record/type/binary.rb10
-rw-r--r--activerecord/lib/active_record/type/serialized.rb5
-rw-r--r--activerecord/test/cases/dirty_test.rb16
-rw-r--r--guides/source/4_2_release_notes.md2
-rw-r--r--guides/source/association_basics.md16
-rw-r--r--guides/source/form_helpers.md32
-rw-r--r--railties/CHANGELOG.md9
-rw-r--r--railties/lib/rails/generators/actions.rb10
-rw-r--r--railties/test/generators/actions_test.rb10
14 files changed, 95 insertions, 43 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 050ec5e649..32a6d5449c 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,6 +1,7 @@
* Allow `config.action_dispatch.trusted_proxies` to accept an IPAddr object.
Example:
+
# config/environments/production.rb
config.action_dispatch.trusted_proxies = IPAddr.new('4.8.15.0/16')
@@ -55,7 +56,7 @@
*Prem Sichanugrist*
-* Deprecated TagAssertions.
+* Deprecated `TagAssertions`.
*Kasper Timm Hansen*
@@ -87,11 +88,11 @@
If you render a different template, you can now pass the `:template`
option to include its digest instead:
- fresh_when @post, template: 'widgets/show'
+ fresh_when @post, template: 'widgets/show'
Pass `template: false` to skip the lookup. To turn this off entirely, set:
- config.action_controller.etag_with_template_digest = false
+ config.action_controller.etag_with_template_digest = false
*Jeremy Kemper*
@@ -145,7 +146,7 @@
*Godfrey Chan*
* Prepend a JS comment to JSONP callbacks. Addresses CVE-2014-4671
- ("Rosetta Flash")
+ ("Rosetta Flash").
*Greg Campbell*
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 396249ac37..f5c520937c 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -26,11 +26,11 @@
*Joel Junström*, *Lucas Uyezu*
* Return an absolute instead of relative path from an asset url in the case
- of the `asset_host` proc returning nil
+ of the `asset_host` proc returning nil.
*Jolyon Pawlyn*
-* Fix `html_escape_once` to properly handle hex escape sequences (e.g. ᨫ)
+* Fix `html_escape_once` to properly handle hex escape sequences (e.g. ᨫ).
*John F. Douthat*
@@ -63,7 +63,7 @@
*Zuhao Wan*
-* Bring `cache_digest` rake tasks up-to-date with the latest API changes
+* Bring `cache_digest` rake tasks up-to-date with the latest API changes.
*Jiri Pospisil*
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index a51523912f..1b11c28087 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -54,7 +54,7 @@ module ActiveModel
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "doesn't match
- # confirmation").
+ # <tt>%{translated_attribute_name}</tt>").
#
# There is also a list of default options supported by every validator:
# +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index b9af8584ae..9d6eb6ad21 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -12,7 +12,7 @@
* Fix has_many :through relation merging failing when dynamic conditions are
passed as a lambda with an arity of one.
- Fixes #16128
+ Fixes #16128.
*Agis Anastasopoulos*
@@ -27,6 +27,7 @@
will not rescue those errors anymore, and just bubble them up, as the other callbacks.
This adds a opt-in flag to enable that behaviour, of not rescuing the errors.
+
Example:
# For not swallow errors in after_commit/after_rollback callbacks.
@@ -51,7 +52,7 @@
* Fix regression on after_commit that didnt fire when having nested transactions.
- Fixes #16425
+ Fixes #16425.
*arthurnn*
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index afd043424d..8c7b0b4be9 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -817,7 +817,7 @@ module ActiveRecord
# person.pets.count # => 2
# person.pets.many? # => true
#
- # You can also pass a block to define criteria. The
+ # You can also pass a +block+ to define criteria. The
# behavior is the same, it returns true if the collection
# based on the criteria has more than one record.
#
@@ -841,7 +841,7 @@ module ActiveRecord
@association.many?(&block)
end
- # Returns +true+ if the given object is present in the collection.
+ # Returns +true+ if the given +record+ is present in the collection.
#
# class Person < ActiveRecord::Base
# has_many :pets
@@ -879,7 +879,7 @@ module ActiveRecord
# Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
# contain the same number of elements and if each element is equal
- # to the corresponding element in the other array, otherwise returns
+ # to the corresponding element in the +other+ array, otherwise returns
# +false+.
#
# class Person < ActiveRecord::Base
diff --git a/activerecord/lib/active_record/type/binary.rb b/activerecord/lib/active_record/type/binary.rb
index d29ff4e494..005a48ef0d 100644
--- a/activerecord/lib/active_record/type/binary.rb
+++ b/activerecord/lib/active_record/type/binary.rb
@@ -22,6 +22,11 @@ module ActiveRecord
Data.new(super)
end
+ def changed_in_place?(raw_old_value, value)
+ old_value = type_cast_from_database(raw_old_value)
+ old_value != value
+ end
+
class Data # :nodoc:
def initialize(value)
@value = value.to_s
@@ -30,10 +35,15 @@ module ActiveRecord
def to_s
@value
end
+ alias_method :to_str, :to_s
def hex
@value.unpack('H*')[0]
end
+
+ def ==(other)
+ other == to_s || super
+ end
end
end
end
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb
index abeea769c4..5b512433b0 100644
--- a/activerecord/lib/active_record/type/serialized.rb
+++ b/activerecord/lib/active_record/type/serialized.rb
@@ -26,6 +26,11 @@ module ActiveRecord
end
end
+ def changed_in_place?(raw_old_value, value)
+ return false if value.nil?
+ subtype.changed_in_place?(raw_old_value, coder.dump(value))
+ end
+
def accessor
ActiveRecord::Store::IndifferentHashAccessor
end
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 0c77eedb52..5cb6b97117 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -682,6 +682,22 @@ class DirtyTest < ActiveRecord::TestCase
assert_not pirate.changed?
end
+ test "in place mutation for binary" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = :binaries
+ serialize :data
+ end
+
+ klass.create!(data: "foo")
+ binary = klass.first
+
+ assert_not binary.changed?
+
+ binary.data << "bar"
+
+ assert binary.changed?
+ end
+
private
def with_partial_writes(klass, on = true)
old = klass.partial_writes?
diff --git a/guides/source/4_2_release_notes.md b/guides/source/4_2_release_notes.md
index 0923d9a1f3..b2f64453dd 100644
--- a/guides/source/4_2_release_notes.md
+++ b/guides/source/4_2_release_notes.md
@@ -123,7 +123,7 @@ Please refer to the [Changelog][railties] for detailed changes.
### Notable changes
* Introduced `web-console` in the default application Gemfile.
- ([Pull Request](https://github.com/rails/rails/pull/16532))
+ ([Pull Request](https://github.com/rails/rails/pull/11667))
* Added a `required` option to the model generator for associations.
([Pull Request](https://github.com/rails/rails/pull/16062))
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index daf4113b66..c9e0fcd939 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -1321,9 +1321,9 @@ When you declare a `has_many` association, the declaring class automatically gai
* `collection<<(object, ...)`
* `collection.delete(object, ...)`
* `collection.destroy(object, ...)`
-* `collection=objects`
+* `collection=(objects)`
* `collection_singular_ids`
-* `collection_singular_ids=ids`
+* `collection_singular_ids=(ids)`
* `collection.clear`
* `collection.empty?`
* `collection.size`
@@ -1399,7 +1399,7 @@ The `collection.destroy` method removes one or more objects from the collection
WARNING: Objects will _always_ be removed from the database, ignoring the `:dependent` option.
-##### `collection=objects`
+##### `collection=(objects)`
The `collection=` method makes the collection contain only the supplied objects, by adding and deleting as appropriate.
@@ -1411,7 +1411,7 @@ The `collection_singular_ids` method returns an array of the ids of the objects
@order_ids = @customer.order_ids
```
-##### `collection_singular_ids=ids`
+##### `collection_singular_ids=(ids)`
The `collection_singular_ids=` method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate.
@@ -1810,9 +1810,9 @@ When you declare a `has_and_belongs_to_many` association, the declaring class au
* `collection<<(object, ...)`
* `collection.delete(object, ...)`
* `collection.destroy(object, ...)`
-* `collection=objects`
+* `collection=(objects)`
* `collection_singular_ids`
-* `collection_singular_ids=ids`
+* `collection_singular_ids=(ids)`
* `collection.clear`
* `collection.empty?`
* `collection.size`
@@ -1895,7 +1895,7 @@ The `collection.destroy` method removes one or more objects from the collection
@part.assemblies.destroy(@assembly1)
```
-##### `collection=objects`
+##### `collection=(objects)`
The `collection=` method makes the collection contain only the supplied objects, by adding and deleting as appropriate.
@@ -1907,7 +1907,7 @@ The `collection_singular_ids` method returns an array of the ids of the objects
@assembly_ids = @part.assembly_ids
```
-##### `collection_singular_ids=ids`
+##### `collection_singular_ids=(ids)`
The `collection_singular_ids=` method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate.
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index 048eb9a6e3..2703e357d5 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -276,7 +276,7 @@ The name passed to `form_for` controls the key used in `params` to access the fo
The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder.
-You can create a similar binding without actually creating `<form>` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example if you had a `Person` model with an associated `ContactDetail` model you could create a form for creating both like so:
+You can create a similar binding without actually creating `<form>` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example, if you had a `Person` model with an associated `ContactDetail` model, you could create a form for creating both like so:
```erb
<%= form_for @person, url: {action: "create"} do |person_form| %>
@@ -534,7 +534,7 @@ Both of these families of helpers will create a series of select boxes for the d
### Barebones Helpers
-The `select_*` family of helpers take as their first argument an instance of `Date`, `Time` or `DateTime` that is used as the currently selected value. You may omit this parameter, in which case the current date is used. For example
+The `select_*` family of helpers take as their first argument an instance of `Date`, `Time` or `DateTime` that is used as the currently selected value. You may omit this parameter, in which case the current date is used. For example:
```erb
<%= select_date Date.today, prefix: :start_date %>
@@ -548,7 +548,7 @@ outputs (with actual option values omitted for brevity)
<select id="start_date_day" name="start_date[day]"> ... </select>
```
-The above inputs would result in `params[:start_date]` being a hash with keys `:year`, `:month`, `:day`. To get an actual `Date`, `Time` or `DateTime` object you would have to extract these values and pass them to the appropriate constructor, for example
+The above inputs would result in `params[:start_date]` being a hash with keys `:year`, `:month`, `:day`. To get an actual `Date`, `Time` or `DateTime` object you would have to extract these values and pass them to the appropriate constructor, for example:
```ruby
Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
@@ -591,9 +591,9 @@ NOTE: In many cases the built-in date pickers are clumsy as they do not aid the
### Individual Components
-Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component `select_year`, `select_month`, `select_day`, `select_hour`, `select_minute`, `select_second`. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example "year" for `select_year`, "month" for `select_month` etc.) although this can be overridden with the `:field_name` option. The `:prefix` option works in the same way that it does for `select_date` and `select_time` and has the same default value.
+Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component `select_year`, `select_month`, `select_day`, `select_hour`, `select_minute`, `select_second`. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example, "year" for `select_year`, "month" for `select_month` etc.) although this can be overridden with the `:field_name` option. The `:prefix` option works in the same way that it does for `select_date` and `select_time` and has the same default value.
-The first parameter specifies which value should be selected and can either be an instance of a `Date`, `Time` or `DateTime`, in which case the relevant component will be extracted, or a numerical value. For example
+The first parameter specifies which value should be selected and can either be an instance of a `Date`, `Time` or `DateTime`, in which case the relevant component will be extracted, or a numerical value. For example:
```erb
<%= select_year(2009) %>
@@ -645,7 +645,7 @@ Unlike other forms making an asynchronous file upload form is not as simple as p
Customizing Form Builders
-------------------------
-As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of `FormBuilder` (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way, you can also subclass `FormBuilder` and add the helpers there. For example
+As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of `FormBuilder` (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way, you can also subclass `FormBuilder` and add the helpers there. For example:
```erb
<%= form_for @person do |f| %>
@@ -684,12 +684,12 @@ If `f` is an instance of `FormBuilder` then this will render the `form` partial,
Understanding Parameter Naming Conventions
------------------------------------------
-As you've seen in the previous sections, values from forms can be at the top level of the `params` hash or nested in another hash. For example in a standard `create`
+As you've seen in the previous sections, values from forms can be at the top level of the `params` hash or nested in another hash. For example, in a standard `create`
action for a Person model, `params[:person]` would usually be a hash of all the attributes for the person to create. The `params` hash can also contain arrays, arrays of hashes and so on.
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 Racks' parameter parser. For example,
+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"
@@ -698,7 +698,7 @@ Rack::Utils.parse_query "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
+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:
```html
<input id="person_name" name="person[name]" type="text" value="Henry"/>
@@ -712,7 +712,7 @@ the `params` hash will contain
and `params[:person][:name]` will retrieve the submitted value in the controller.
-Hashes can be nested as many levels as required, for example
+Hashes can be nested as many levels as required, for example:
```html
<input id="person_address_city" name="person[address][city]" type="text" value="New York"/>
@@ -724,7 +724,7 @@ will result in the `params` hash being
{'person' => {'address' => {'city' => 'New York'}}}
```
-Normally Rails ignores duplicate parameter names. If the parameter name contains an empty set of square brackets [] then they will be accumulated in an array. If you wanted people to be able to input multiple phone numbers, you could place this in the form:
+Normally Rails ignores duplicate parameter names. If the parameter name contains an empty set of square brackets `[]` then they will be accumulated in an array. If you wanted users to be able to input multiple phone numbers, you could place this in the form:
```html
<input name="person[phone_number][]" type="text"/>
@@ -732,11 +732,11 @@ Normally Rails ignores duplicate parameter names. If the parameter name contains
<input name="person[phone_number][]" type="text"/>
```
-This would result in `params[:person][:phone_number]` being an array.
+This would result in `params[:person][:phone_number]` being an array containing the inputted phone numbers.
### Combining Them
-We can mix and match these two concepts. For example, one element of a hash might be an array as in the previous example, or you can have an array of hashes. For example a form might let you create any number of addresses by repeating the following form fragment
+We can mix and match these two concepts. One element of a hash might be an array as in the previous example, or you can have an array of hashes. For example, a form might let you create any number of addresses by repeating the following form fragment
```html
<input name="addresses[][line1]" type="text"/>
@@ -746,7 +746,7 @@ We can mix and match these two concepts. For example, one element of a hash migh
This would result in `params[:addresses]` being an array of hashes with keys `line1`, `line2` and `city`. Rails decides to start accumulating values in a new hash whenever it encounters an input name that already exists in the current hash.
-There's a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can be usually replaced by hashes, for example instead of having an array of model objects one can have a hash of model objects keyed by their id, an array index or some other parameter.
+There's a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can usually be replaced by hashes; for example, instead of having an array of model objects, one can have a hash of model objects keyed by their id, an array index or some other parameter.
WARNING: Array parameters do not play well with the `check_box` helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The `check_box` helper fakes this by creating an auxiliary hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted and if it is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new array element. It is preferable to either use `check_box_tag` or to use hashes instead of arrays.
@@ -856,7 +856,7 @@ Or if you don't want to render an `authenticity_token` field:
Building Complex Forms
----------------------
-Many apps grow beyond simple forms editing a single object. For example when creating a `Person` you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary.
+Many apps grow beyond simple forms editing a single object. For example, when creating a `Person` you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary.
### Configuring the Model
@@ -908,7 +908,7 @@ end
```
The `fields_for` yields a form builder. The parameters' name will be what
-`accepts_nested_attributes_for` expects. For example when creating a user with
+`accepts_nested_attributes_for` expects. For example, when creating a user with
2 addresses, the submitted parameters would look like:
```ruby
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 2a09ccf61a..7d6521b2a8 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,6 +1,13 @@
+* Fix a bug in the `gem` method for Rails templates when non-String options
+ are used.
+
+ Fixes #16709.
+
+ *Yves Senn*
+
* The [web-console](https://github.com/rails/web-console) gem is now
installed by default for new applications. It can help you debug
- development exceptions by spawnig an interactive console in its cause
+ development exceptions by spawning an interactive console in its cause
binding.
*Ryan Dao*, *Genadi Samokovarov*, *Guillermo Iguaran*
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 4709914947..b2c9d12996 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -268,11 +268,13 @@ module Rails
# Surround string with single quotes if there is no quotes.
# Otherwise fall back to double quotes
- def quote(str)
- if str.include?("'")
- str.inspect
+ def quote(value)
+ return value.inspect unless value.is_a? String
+
+ if value.include?("'")
+ value.inspect
else
- "'#{str}'"
+ "'#{value}'"
end
end
end
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index a4337926d1..2206e389b5 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -79,6 +79,16 @@ class ActionsTest < Rails::Generators::TestCase
assert_file 'Gemfile', /gem 'rspec', github: 'dchelimsky\/rspec', tag: '1\.2\.9\.rc1'/
end
+ def test_gem_with_non_string_options
+ run_generator
+
+ action :gem, 'rspec', require: false
+ action :gem, 'rspec-rails', group: [:development, :test]
+
+ assert_file 'Gemfile', /^gem 'rspec', require: false$/
+ assert_file 'Gemfile', /^gem 'rspec-rails', group: \[:development, :test\]$/
+ end
+
def test_gem_falls_back_to_inspect_if_string_contains_single_quote
run_generator