1
0
Fork 0
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:
Sean Griffin 2016-05-31 09:56:19 -04:00
parent 998bbbcc0e
commit ff4986b917
4 changed files with 21 additions and 5 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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)