aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/aggregations.rb6
-rw-r--r--activerecord/test/cases/aggregations_test.rb5
-rw-r--r--activerecord/test/models/customer.rb1
4 files changed, 17 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 14a6c3c9f7..dfd9a07997 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Hashes can once again be passed to setters of `composed_of`, if all of the
+ mapping methods are methods implemented on `Hash`.
+
+ Fixes #25978.
+
+ *Sean Griffin*
+
* Fix the SELECT statement in `#table_comment` for MySQL.
*Takeshi Akima*
diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb
index 8bed5bca28..9f965052c5 100644
--- a/activerecord/lib/active_record/aggregations.rb
+++ b/activerecord/lib/active_record/aggregations.rb
@@ -261,8 +261,10 @@ module ActiveRecord
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
+ hash_from_multiparameter_assignment = part.is_a?(Hash) &&
+ part.each_key.all? { |k| k.is_a?(Integer) }
+ if hash_from_multiparameter_assignment
+ raise ArgumentError unless part.size == part.each_key.max
part = klass.new(*part.sort.map(&:last))
end
diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb
index 8a728902a8..4e865264c7 100644
--- a/activerecord/test/cases/aggregations_test.rb
+++ b/activerecord/test/cases/aggregations_test.rb
@@ -143,6 +143,11 @@ class AggregationsTest < ActiveRecord::TestCase
customers(:barney).fullname = { first: "Barney", last: "Stinson" }
assert_equal "Barney STINSON", customers(:barney).name
end
+
+ def test_assigning_hash_without_custom_converter
+ customers(:barney).fullname_no_converter = { first: "Barney", last: "Stinson" }
+ assert_equal({ first: "Barney", last: "Stinson" }.to_s, customers(:barney).name)
+ end
end
class OverridingAggregationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/models/customer.rb b/activerecord/test/models/customer.rb
index 3338aaf7e1..d464759430 100644
--- a/activerecord/test/models/customer.rb
+++ b/activerecord/test/models/customer.rb
@@ -7,6 +7,7 @@ class Customer < ActiveRecord::Base
composed_of :non_blank_gps_location, :class_name => "GpsLocation", :allow_nil => true, :mapping => %w(gps_location gps_location),
:converter => lambda { |gps| self.gps_conversion_was_run = true; gps.blank? ? nil : GpsLocation.new(gps)}
composed_of :fullname, :mapping => %w(name to_s), :constructor => Proc.new { |name| Fullname.parse(name) }, :converter => :parse
+ composed_of :fullname_no_converter, :mapping => %w(name to_s), class_name: "Fullname"
end
class Address