mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Ensure hashes can be passed to attributes using composed_of
This behavior was broken by 36e9be85
. When the value is assigned
directly, either through mass assignment or directly assigning a hash,
the hash gets passed through to this writer method directly. While this
is intended to handle certain cases, when an explicit converter has been
provided, we should continue to use that instead. The positioning of the
added guard caused the new behavior to override that case.
Fixes #25210
This commit is contained in:
parent
998bbbcc0e
commit
ff4986b917
4 changed files with 21 additions and 5 deletions
|
@ -1,3 +1,8 @@
|
|||
* Ensure hashes can be assigned to attributes created using `composed_of`.
|
||||
Fixes #25210.
|
||||
|
||||
*Sean Griffin*
|
||||
|
||||
* Fix logging edge case where if an attribute was of the binary type and
|
||||
was provided as a Hash.
|
||||
|
||||
|
|
|
@ -256,15 +256,16 @@ module ActiveRecord
|
|||
def writer_method(name, class_name, mapping, allow_nil, converter)
|
||||
define_method("#{name}=") do |part|
|
||||
klass = class_name.constantize
|
||||
if part.is_a?(Hash)
|
||||
raise ArgumentError unless part.size == part.keys.max
|
||||
part = klass.new(*part.sort.map(&:last))
|
||||
end
|
||||
|
||||
unless part.is_a?(klass) || converter.nil? || part.nil?
|
||||
part = converter.respond_to?(:call) ? converter.call(part) : klass.send(converter, part)
|
||||
end
|
||||
|
||||
if part.is_a?(Hash)
|
||||
raise ArgumentError unless part.size == part.keys.max
|
||||
part = klass.new(*part.sort.map(&:last))
|
||||
end
|
||||
|
||||
if part.nil? && allow_nil
|
||||
mapping.each { |key, _| self[key] = nil }
|
||||
@aggregation_cache[name] = nil
|
||||
|
|
|
@ -138,6 +138,11 @@ class AggregationsTest < ActiveRecord::TestCase
|
|||
assert_equal 'Barnoit GUMBLEAU', customers(:barney).fullname.to_s
|
||||
assert_kind_of Fullname, customers(:barney).fullname
|
||||
end
|
||||
|
||||
def test_assigning_hash_to_custom_converter
|
||||
customers(:barney).fullname = { first: "Barney", last: "Stinson" }
|
||||
assert_equal "Barney STINSON", customers(:barney).name
|
||||
end
|
||||
end
|
||||
|
||||
class OverridingAggregationsTest < ActiveRecord::TestCase
|
||||
|
|
|
@ -64,7 +64,12 @@ class Fullname
|
|||
|
||||
def self.parse(str)
|
||||
return nil unless str
|
||||
new(*str.to_s.split)
|
||||
|
||||
if str.is_a?(Hash)
|
||||
new(str[:first], str[:last])
|
||||
else
|
||||
new(*str.to_s.split)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(first, last = nil)
|
||||
|
|
Loading…
Reference in a new issue