提交 ff4986b9 编写于 作者: S Sean Griffin

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
上级 998bbbcc
* 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 @@ def reader_method(name, class_name, mapping, allow_nil, constructor)
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 @@ def test_custom_converter
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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册