mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #33437 from CodingAnarchy/delegate_missing_allow_nil
Add :allow_nil option to delegate_missing_to
This commit is contained in:
commit
639d7beb0b
5 changed files with 44 additions and 5 deletions
|
@ -1,3 +1,18 @@
|
||||||
|
* Method calls on singular attachments return `nil` when no file is attached.
|
||||||
|
|
||||||
|
Previously, assuming the following User model, `user.avatar.filename` would
|
||||||
|
raise a `Module::DelegationError` if no avatar was attached:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class User < ApplicationRecord
|
||||||
|
has_one_attached :avatar
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
They now return `nil`.
|
||||||
|
|
||||||
|
*Matthew Tanous*
|
||||||
|
|
||||||
* The mirror service supports direct uploads.
|
* The mirror service supports direct uploads.
|
||||||
|
|
||||||
New files are directly uploaded to the primary service. When a
|
New files are directly uploaded to the primary service. When a
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module ActiveStorage
|
module ActiveStorage
|
||||||
# Representation of a single attachment to a model.
|
# Representation of a single attachment to a model.
|
||||||
class Attached::One < Attached
|
class Attached::One < Attached
|
||||||
delegate_missing_to :attachment
|
delegate_missing_to :attachment, allow_nil: true
|
||||||
|
|
||||||
# Returns the associated attachment record.
|
# Returns the associated attachment record.
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
* `delegate_missing_to` would raise a `DelegationError` if the object
|
||||||
|
delegated to was `nil`. Now the `allow_nil` option has been added to enable
|
||||||
|
the user to specify they want `nil` returned in this case.
|
||||||
|
|
||||||
|
*Matthew Tanous*
|
||||||
|
|
||||||
* `truncate` would return the original string if it was too short to be truncated
|
* `truncate` would return the original string if it was too short to be truncated
|
||||||
and a frozen string if it were long enough to be truncated. Now truncate will
|
and a frozen string if it were long enough to be truncated. Now truncate will
|
||||||
consistently return an unfrozen string regardless. This behavior is consistent
|
consistently return an unfrozen string regardless. This behavior is consistent
|
||||||
|
@ -19,5 +25,4 @@
|
||||||
|
|
||||||
*Jordan Thomas*
|
*Jordan Thomas*
|
||||||
|
|
||||||
|
|
||||||
Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activesupport/CHANGELOG.md) for previous changes.
|
Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activesupport/CHANGELOG.md) for previous changes.
|
||||||
|
|
|
@ -274,8 +274,9 @@ class Module
|
||||||
# variables, methods, constants, etc.
|
# variables, methods, constants, etc.
|
||||||
#
|
#
|
||||||
# The delegated method must be public on the target, otherwise it will
|
# The delegated method must be public on the target, otherwise it will
|
||||||
# raise +NoMethodError+.
|
# raise +DelegationError+. If you wish to instead return +nil+,
|
||||||
def delegate_missing_to(target)
|
# use the <tt>:allow_nil</tt> option.
|
||||||
|
def delegate_missing_to(target, allow_nil: nil)
|
||||||
target = target.to_s
|
target = target.to_s
|
||||||
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
|
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
|
||||||
|
|
||||||
|
@ -295,7 +296,11 @@ class Module
|
||||||
super
|
super
|
||||||
rescue NoMethodError
|
rescue NoMethodError
|
||||||
if #{target}.nil?
|
if #{target}.nil?
|
||||||
|
if #{allow_nil == true}
|
||||||
|
return nil
|
||||||
|
else
|
||||||
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
|
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
|
||||||
|
end
|
||||||
else
|
else
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
|
@ -92,6 +92,16 @@ DecoratedTester = Struct.new(:client) do
|
||||||
delegate_missing_to :client
|
delegate_missing_to :client
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DecoratedMissingAllowNil
|
||||||
|
delegate_missing_to :case, allow_nil: true
|
||||||
|
|
||||||
|
attr_reader :case
|
||||||
|
|
||||||
|
def initialize(kase)
|
||||||
|
@case = kase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class DecoratedReserved
|
class DecoratedReserved
|
||||||
delegate_missing_to :case
|
delegate_missing_to :case
|
||||||
|
|
||||||
|
@ -382,6 +392,10 @@ class ModuleTest < ActiveSupport::TestCase
|
||||||
assert_equal "name delegated to client, but client is nil", e.message
|
assert_equal "name delegated to client, but client is nil", e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_delegate_missing_to_returns_nil_if_allow_nil_and_nil_target
|
||||||
|
assert_nil DecoratedMissingAllowNil.new(nil).name
|
||||||
|
end
|
||||||
|
|
||||||
def test_delegate_missing_to_affects_respond_to
|
def test_delegate_missing_to_affects_respond_to
|
||||||
assert_respond_to DecoratedTester.new(@david), :name
|
assert_respond_to DecoratedTester.new(@david), :name
|
||||||
assert_not_respond_to DecoratedTester.new(@david), :private_name
|
assert_not_respond_to DecoratedTester.new(@david), :private_name
|
||||||
|
|
Loading…
Reference in a new issue